packages feed

futhark 0.25.8 → 0.25.9

raw patch · 23 files changed

+3771/−487 lines, 23 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Futhark.Util.CMath: ldexp :: Double -> CInt -> Double
+ Futhark.Util.CMath: ldexpf :: Float -> CInt -> Float

Files

+ CHANGELOG.md view
@@ -0,0 +1,3117 @@+# Changelog++All notable changes to this project will be documented in this file.++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.9]++### Added++* The `cuda` and `hip` backends now generate faster code for `scan`s+  that have been fused with `map`s that internally produce arrays.+  Work by Anders Holst and Christian Påbøl Jacobsen.++* `f16.ldexp`, `f32.ldexp`, `f64.ldexp`, corresponding to the+  functions in the C math library.++### Fixed++* Incorrect data dependency information for `scatter` and `vjp` could+  cause invalid simplification.++* Barrier divergence in certain complicated kernels that contain both+  bounds checks and intragroup scans.++## [0.25.8]++### Added++* FutharkScript now has a `$loadbytes` builtin function for reading+  arbitrary bytes into Futhark programs.++* `futhark profile` can now process reports produced by the C API+  function `futhark_context_report()`.++* `futhark profile` now also produces a timeline of events.++### Fixed++* `futhark literate` no longer fails if the final line is a directive+  without a trailing newline.++* Parser now allows arbitrary patterns in function parameters and+  `let` bindings, although the type checker will reject any that are+  refutable (#2017).++* Avoid generating invalid code in cases where deduplicated sum types+  are exposed through entry points (#1960).++* A bug in data dependency analysis for histogram operations would+  mistakenly classify some loop parameters as redundant, leaving to+  code being removed.++## [0.25.7]++### Added++* `futhark autotune` now supports `hip` backend.++* Better parallelisation of `scatter` when the target is+  multidimensional (#2035).++### Fixed++* Very large `iota`s now work.++* Lambda lifting in `while` conditions (#2038).++* Size expressions in local function parameters had an interesting+  interaction with defunctionalisation (#2040).++* The `store` command in server executables did not properly+  synchronise when storing opaque values, which would lead to+  use-after-free errors.++## [0.25.6]++### Added++* The various C API functions that accept strings now perform a copy,+  meaning the caller does not have to keep the strings alive.++* Slightly better lexer error messages.++* Fusion across slicing is now possible in some cases.++* New tool: `futhark profile`.++### Fixed++* Inefficient locking for certain segmented histograms (#2024).++## [0.25.5]++### Added++* `futhark repl` now has a `:format` command.  Work by Dominic+  Kennedy.++### Fixed++* Textual floating-point numbers printed by executables now always+  print enough digits to not hide information.  Binary output is+  unchanged.++* Invalid CSE on constants could crash the compiler (#2021).++## [0.25.4]++### Fixed++* Invalid simplification (#2015).++* Rarely occurring deadlock for fused map-scan compositions in CUDA+  backend, when a bounds check failed in the map function.++* Compiler and interpreter crash for tricky interactions of abstract+  types and sizes (#2016).  Solved by banning such uses - in principle+  this could break code.++* Incomplete alias tracking could cause removal of necessary copies,+  leading to compiler crash (#2018).++## [0.25.3]++### Added++* pyopencl backend: compatibility with future versions of PyOpenCL.++* New backend: hip.++### Fixed++* Exotic problems related to intra-group reductions with array+  operands.  (Very rare in real code, although sometimes generated by+  AD.)++* Interpreter issue related to sizes in modules (#1992, #1993, #2002).++* Incorrect insertion of size arguments in in complex cases (#1998).++* Incorrect handling of `match` in lambda lifting (#2000).++* Regression in checking of consumption (#2007).++* Error in type checking of horisontally fused `scatter`s could crash+  the compiler (#2009).++* Size-polymorphic value bindings with existential sizes are now+  rejected by type checker (#1993).++* Single pass scans with complicated fused map functions were+  insufficiently memory-expanded (#2023).++* Invalid short circuiting (#2013).++## [0.25.2]++### Added++* Flattening/unflattening as the final operation in an entry point no+  longer forces a copy.++* The `opencl` backend no longer *always* fails on platforms that do+  not support 64-bit integer atomics, although it will still fail if+  the program needs them.++* Various performance improvements to the compiler itself;+  particularly the frontend.  It should be moderately faster.++### Fixed++* Code generation for `f16` literals in CUDA backend (#1979).++* Branches that return arrays differing in sign of their stride+  (#1984).++## [0.25.1]++### Added++* Arbitrary expressions of type `i64` are now allowed as sizes.  Work+  by Lubin Bailly.++* New prelude function `resize`.++### Removed++* The prelude functions `concat_to` and `flatten_to`.  They are often+  not necessary now, and otherwise `resize` is available.++### Changed++* The prelude functions `flatten` and `unflatten` (and their+  multidimensional variants), as well as `split`, now have more+  precise types.++* Local and anonymous (lambda) functions that *must* return unique+  results (because they are passed to a higher order function that+  requires this) must now have an explicit return type ascription that+  declares this, using `*`.  This is very rare (in practice+  unobserved) in real programs.++### Fixed++* `futhark doc` produced some invalid links.++* `flatten` did not properly check for claimed negative array sizes.++* Type checker crash on some ill-typed programs (#1926).++* Some soundness bugs in memory short circuiting (#1927, #1930).++* Another compiler crash in block tiling (#1933, #1940).++* Global arrays with size parameters no longer have aliases.++* `futhark eval` no longer crashes on ambiguously typed expressions (#1946).++* A code motion pass was ignorant of consumption constraints, leading+  to compiler crash (#1947).++* Type checker could get confused and think unknown sizes were+  available when they really weren't (#1950).++* Some index optimisations removed certificates (#1952).++* GPU backends can now transpose arrays whose size does not fit in a+  32-bit integer (#1953).++* Bug in alias checking for the core language type checker (#1949).+  Actually (finally) a proper fix of #803.++* Defunctionalisation duplicates less code (#1968).++## [0.24.3]++### Fixed++* Certain cases of noninlined functions in `multicore` backend.++* Defunctionalisation of `match` where the constructors carry+  functions (#1917).++* Shape coercions involving sum types (#1918).  This required+  tightening the rules a little bit, so some coercions involving+  anonymous sizes may now be rejected.  Add expected sizes as needed.++* Defunctionalisation somtimes forgot about sizes bound at top level+  (#1920).++## [0.24.2]++### Added++* `futhark literate` (and FutharkScript in general) is now able to do+  a bit of type-coercion of constants.++### Fixed++* Accumulators (produced by AD) had defective code generation for+  intra-group GPU kernel versions. (#1895)++* The header file generated by `--library` contained a prototype for+  an undefined function. (#1896)++* Crashing bug in LSP caused by stray `undefined` (#1907).++* Missing check for anonymous sizes in type abbreviations (#1903).++* Defunctionalisation crashed on projection of holes.++* Loop optimisation would sometimes remove holes.++* A potential barrier divergence for certain GPU kernels that fail+  bounds checking.++* A potential infinite loop when looking up aliases (#1915).++* `futhark literate`: less extraneous whitespace.++## [0.24.1]++### Added++* The manifest file now lists which tuning parameters are relevant for+  each entry point. (#1884)++* A command `tuning_params` has been added to the server protocol.++### Changed++* If part of a function parameter is marked as consuming ("unique"),+  the *entire* parameter is now marked as consuming.++### Fixed++* A somewhat obscure simplification rule could mess up use of memory.++* Corner case optimisation for mapping over `iota` (#1874).++* AD for certain combinations of `map` and indexing (#1878).++* Barrier divergence in generated code in some exotic cases (#1883).++* Handling of higher-order holes (#1885).++## [0.23.1]++### Added++* `f16.log1p`/`f32.log1p`/`f64.log1p` by nbos (#1820).++* Better syntax errors for invalid use of `!`.++* `futhark literate` now supports a `$loadaudio` builtin function for loading+  audio to Futhark programs (#1829).++* You can now mix consumption and higher-order terms in slightly more+  cases (#1836).++* `futhark pkg` now invokes Git directly rather than scraping+  GitHub/GitLab.  This means package paths can now refer to any Git+  repository, as long as `git clone` works.  In particular, you can+  use private and self-hosted repositories.++* Significant reduction in compilation time by doing internal sanity+  checks in separate thread.++* New command: `futhark eval`. Evaluates Futhark expressions+  provided as command line arguments, optionally allowing a file+  import (#1408).++* `script input` now allows the use of `$loaddata`.++* Datasets used in `futhark test` and `futhark bench` can now be named+  (#1859).++* New command `futhark benchcmp` by William Due.++### Changed++* The C API function `futhark_context_new_with_command_queue()` for+  the OpenCL backend has been replaced with a configuration setting+  `futhark_context_config_set_command_queue()`.++### Fixed++* Minor parser regression that mostly affects the REPL (#1822).++* Parser did not recognise custom infix operators that did not have a+  builtin operator as prefix (#1824).++* GPU backends: expansion of irregular nested allocations involving+  consumption (#1837, #1838).++* CLI executables now handle entry points with names that are not+  valid C identifiers (#1841).++* Various oversights in the type checking of uniqueness annotations+  for higher-order functions (#1842).++* Invalid short-circuiting could cause compiler crashes (#1843).++* Defunctionalisation could mess up sum types, leading to invalid code+  generation by internalisation, leading to a compiler crash (#1847).++* The `#[break]` attribute now provides the right environment to+  `futhark repl`, allowing local variables to be inspected.++* Simplification of concatenations (#1851).++* Array payloads in sum types no longer need parens (#1853).++* When a file is loaded with `futhark repl`, `local` declarations are+  now available.++* Missing alias propagation when pattern matching incompletely known+  sum types (#1855).++* `reduce_by_index` and `hist` were in some cases unable to handle+  input sizes that do not fit in a 32-bit integer.++* A fusion bug related to fusing across transpositions could result in+  a compiler crash (#1858).++## [0.22.7]++### Added++* `futhark literate` now supports an `:audio` directive for producing audio+  files from arrays of `i8` (#1810).++* `futhark multicore` now parallelises copies (#1799).++* `futhark multicore` now uses an allocator that better handles large+  allocations (#1768).++### Fixed++* Some record field names could cause generation of invalid C API names (#1806).++* Memory block merging was extremely and unnecessarily slow for+  programs with many entry points.++* Simplification mistake could lead to out-of-bounds reads (#1808).++* `futhark lsp` now handles some bookkeeping messages sent by Eglot.++* Parser can now handle arbitrarily complex chaining of indexing and+  projection.++* Detect and complain about source files without .fut extension (#1813).++* Overly conservative checking of whether a function parameter is+  allowed by be consumed - it was disallowed if it contained any+  scalars (#1816).++## [0.22.6]++### Added++* Slightly better type errors for sum types (#1792).++* Better tracing output in interpreter (#1795).++* Improved optimisation of code that uses zero-element arrays+  (sometimes used for type witnesses).++### Fixed++* Mishandling of bounds checks in parallel backends could cause+  compiler crashes (#1791).++* Mis-simplification of certain sequentialised scatters into+  single-element arrays (#1793).++* Invalid `scatter` fusion would cause an internal compiler error+  (#1794).++* The code generator flipped the order of `match` cases.++* Simpification of concatenations (#1796).++* Defunctionalisation error for fancy size programming (#1798).++* Code generation for load-unbalanced reductions in multicore backend+  (#1800).++* Futhark now works on CUDA 12 (#1801).++* `mul_hi` and `mad_hi` for signed integer types now actually do+  signed multiplication (previously it was always unsigned).++## [0.22.5]++### Added++* Memory short circuiting now also applied to the `multicore` backend.++* Fixes for AD of `scan` with nonscalar operators.  Work by Lotte+  Bruun and Ulrik Larsen.++* Generalised histograms now supported in AD.  Work by Lotte Bruun and+  Ulrik Larsen.++* OpenCL kernels now embed group size information, which can+  potentially be used for better register allocation by the OpenCL+  implementation.++### Fixed++* A hole in the type checker that allowed one to sneak functions out+  of conditionals (#1787).++* `futhark repl`: unsigned integers are now printed correctly.++* A bug in the type-checking of `match` (#1783).++* Missing sequencing in type-checking of in-place `let` expressions (#1786).++* Crash in defunctionaliser caused by duplicate parameter names+  (#1780).++* Infelicities in multicore codegen for scans (#1777).++## [0.22.4]++### Added++* Memory short circuiting, a major new optimisation by Philip+  Munksgaard that avoids copies by constructing values in-place.++### Fixed++* `assert` was sometimes optimised away by CSE.++* `futhark literate` now handles type abbreviations in entry points+  (#1750).++* Handling of non-inlined functions in GPU code.  Still very restricted.++* Uniqueness checking bug (#1751).++* Simplification bug (#1753).++* A bug related to optimisation of scalar code migrated to GPU.++* Memory optimisation bug for top-level constants (#1755).++* Handling of holes in defunctionalisation (again).++* A few cases where optimisation (safely but perhaps confusingly)+  removed bounds checks (#1758).++* Futhark now works on Windows again (#1734).  This support remains+  very flaky and not well tested.++* Type inference of field projection (#1762).++## [0.22.3]++### Fixed++* Non-server executables neglected to synchronise before printing results (#1731).++* Fixed handling of holes in defunctionalisation (#1738).++* Ascription of higher-order modules (#1741).++* Fixed compiler crash when attempting to tile irregular parallelism (#1739).++* Incorrect regularity checking in loop interchange (#1744).++* Pattern match exhaustiveness of bools (#1748).++* Improper consumption checking of nonlocal bindings (#1749).++## [0.22.2]++### Added++* `futhark repl` is now delightfully more colourful.++* `futhark repl` no longer prints scalar types with type suffixes (#1724).++* `futhark pyopencl` executables now accept ``--build-option``.++* New functions: `f16.nextafter`, `f32.nextafter`, `f64.nextafter`,+  matching the ones in the C math library.++* `futhark literate` now prints directives in the output exactly as+  they appear in the source.++### Fixed++* Diagnostics will no longer contain control codes when output is a+  file.++* CLI executables now fail when printing an opaque instead of+  producing garbage.  This improves handling of some incorrect uses of+  `auto output` (#1251).++## [0.22.1]++### Removed++* Removed prelude functions `reduce_stream`, `map_stream`,+  `reduce_stream_per`, and `reduce_map_per`.++### Fixed++* Various fixes to scalar migration (#1721).++## [0.21.15]++### Fixed++* Corrupted OOM error messages.++* Excessive internal fragmentation for some programs (#1715).++## [0.21.14]++### Fixed++* `replicate` was broken for sizes that didn't fit in `i32`.++* Transposition of empty arrays in interpreter (#1700).++* Exotic simplification error (#1309).++* Rare race condition could lead to leaking of error message memory in+  `multicore` and `ispc` backends (#1709).++* Overzealous aliasing for built-in overloaded types (#1711).++## [0.21.13]++### Added++* New fusion engine by Amar Topalovic and Walter Restelli-Nielsen.+  Fuses more, which is good for some programs and bad for others.+  Most programs see no change.  This is mainly a robust foundation for+  further improvements.++* New experimental backend: `ispc`.  By Louis Marott Normann,+  Kristoffer August Kortbæk, William Pema Norbu Holmes Malling, and+  Oliver Bak Kjersgaard Petersen.++* New prelude functions: `hist`, `spread`.  These function as+  non-consuming variants of `reduce_by_index` and `scatter`.++* Using `==` to compare arrays is now deprecated.++* New command: `futhark tokens`.  You probably don't care about this one.++* In the C API, opaque types that correspond to tuples or records can+  now have their elements inspected and be created from elements+  (#1568).++* New server protocol commands: `types`, `fields`, `entry_points`.++* Tuples and records can now be passed from FutharkScript to Futhark+  entry points (#1684).++### Fixed++* Sometimes missing cases in `match` expressions were not detected.++* A defective simplification rule could in very rare cases lead to+  infinite recursion in the compiler (#1685).++* Some broken links in `futhark doc` output (#1686).++* Incorrect checking of whether a function parameter is consumable+  based on its type (#1687).++* Missing aliases for functions that return multiple aliased values+  (#1690).++* `new`/`values` functions for GPU backends are now properly+  asynchronous (#1664).  This may uncover bugs in application code.++## [0.21.12]++### Added++* Somewhat simplified the handling of "uniqueness types" (which is a+  term we are moving away from).  You should never see `*` in+  non-function types, and they are better thought of as effect+  indicators.++* `futhark literate`: prints tracing output (and other logging+  messages that may occur) when run with `-v` (#1678).++* Entry points can now be any valid Futhark identifier.++### Fixed++* `futhark test -C` was broken.++* `futhark_context_free()` for the GPU backends neglected to free some+  memory used for internal bookkeeping, which could lead to memory+  leaks for processes that repeatedly create and destroy contexts+  (#1676).++* FutharkScript now allows `'` in names.++* `futhark lsp` now handles warnings in programs that also have errors.++## [0.21.11]++### Added++* The CUDA backend now supports compute capability 8.6 and 8.7.++* Philip Børgesen has implemented a new optimisation for GPU backends+  that migrates scalar work to the GPU, in order to reduce+  synchronisation.  This results in major speedup for some programs.++* String literals are now allowed in `input` blocks.++* Experimental and undocumented support for automatic differentiation,+  available on the secret menu.++* Assertions and attributes are now ignored when used as size+  expressions.  E.g. `iota (assert p n) 0` now has size `n`.++* `futhark test` only runs the interpreter if passed `-i`.++* `futhark literate` now shows progress bars when run with `-v`.++### Fixed++* `futhark lsp` is now better at handling multiple files (#1647).++* Incorrect handling of local quantification when determining type+  equivalence in during module type ascription (#1648).++* Incorrect checking of liftedness when instantiating polymorphic+  functions during module type ascription.++* Tightened some restrictions on the use of existential sizes that+  could otherwise lead to compiler crashes (#1650).  This restriction+  is perhaps a bit *too* might and it may be possible to loosen it in+  the future.++* Another defunctorisation bug (#1653).  Somehow we find these every+  time Martin Elsman writes a nontrivial Futhark program.++* `futhark bench`: convergence phase now does at least `--runs` runs.++* Errors and warnings no longer awkwardly mixed together in console output.++* Slightly better type errors for ambiguous sizes (#1661).++* Better type errors for module ascription involving nested modules+  (#1660).++* `futhark doc`: some formatting bugs.++* `futhark doc` didn't notice all `local` module types (#1666).++* Missing consumption check in optimisation could lead to ICE (#1669).++## [0.21.10]++### Added++* New math functions: `f16.erf`, `f32.erf`, `f64.erf`.++* New math functions: `f16.erfc`, `f32.erfc`, `f64.erfc`.++* New math functions: `f16.cbrt`, `f32.cbrt`, `f64.cbrt`.++### Fixed++* Variables being indexed now have correct source spans in AST.++* `futhark lsp`s hover information now contains proper range information.++* `futhark query` and `futhark lsp` incorrectly thought size+  parameters had type `i32`.++* `futhark doc` put documentation for prelude modules in the wrong+  location (which also led to messed-up style sheets).++## [0.21.9]++### Added++* Sun Haoran has implemented unnamed typed holes, with syntax `???`.++* Sun Haoran has implemented the beginnings of a language server:+  `futhark lsp`.  A VSCode language extension is available on the+  marketplace, but the language server should work with any editor.++* Crucial new command: `futhark thanks`.++* The GPU backends now support a caching mechanism for JIT-compiled+  code, significantly improving startup times.  Use the+  `futhark_context_config_set_cache_file()` in the C API, the+  `--cache-file` option on executables, or the `--cache-extension`+  option on `futhark test` and `futhark bench`.  These also work for+  the non-GPU backends, but currently have no effect.  (#1614)++* Aleksander Junge has improved `futhark bench` such that it+  intelligently chooses how many runs to perform (#1335).++### Fixed++* Incomplete simplification would cause some instances of nested+  parallelism to require irregular allocations (#1610).++* Missing alias checking for a simplification rule related to in-place+  updates (#1615, #1628).++* Incorrect code generation for certain copies of transposed arrays+  (#1627).++* Fusion would mistakenly try to treat some loops with irregular sizes+  (#1631).++* Memory annotation bug for non-inlined functions (#1634).++## [0.21.8]++### Added++* Slightly better parse errors (again).++* `futhark literate` now supports a `file:` option in `:img` and+  `:video` directives (#1491).++### Fixed++* Improved hoisting of size computations.  This could cause some+  regular nested parallel programs to run into compiler limitations,+  as if they were irregular.++* Rare code generation bug for histograms (#1609).++## [0.21.7]++### Added++* `futhark check-syntax`: check syntactic validity of a program+  file, without type-checking.++* Parsing multi-file programs is now parallelised, making it+  *slightly* faster.++* Reloading a large program in `futhark repl` is now faster, as long+  as not too many of its files have been modified (#1597).++### Fixed++* Mistake in occurs check could cause infinite loop in type checker+  for programs with type errors (#1599).++## [0.21.6]++### Added++* `futhark bench` now explicitly notes when a tuning file is not+  present.++* `futhark bench`, `futhark test` and friends are now better at+  handling fatally terminating programs (e.g. segmentation faults).++* Generated C code is now a lot smaller for large programs, as error+  recovery has been more centralised (#1584).++### Fixed++* Some bugs in checking for local memory capacity for particularly+  exotic generated code.++* Insufficient hoisting of allocation sizes led to problems with+  memory expansion in rare cases (#1579).++* Conversion of floating-point NaNs and infinities to integers now+  well defined (produces zero) (#1586).++* Better handling of OOM for certain short-lived CPU-side allocations (#1585).++## [0.21.5]++### Added++* API functions now return more precise error codes in some cases.++* Out-of-memory errors contain more information.++### Fixed++* Yet another in-place lowering issue (#1569).++* Removed unnecessary bounds checks in register tiling, giving about+  1.8x speedup on e.g. matrix multiplication on newer NVIDIA GPUs.++* A parser bug erroneously demanded whitespace in some type+  expressions (#1573).++* Some memory was not being freed correctly when shutting down OpenCL+  and CUDA contexts, which could lead to memory leaks in processes+  that created and freed many contexts.++* An incorrect copy-removal in some exotic cases (#1572).++* 'restore'-functions might perform undefined pointer arithmetic when+  passed garbage.++## [0.21.4]++### Fixed++* A size inference bug in type checking of `loop`s (#1565).++* Exotic flattening bug (#1563).++* Segmented `reduce_by_index` with fairly small histogram size would+  use vastly more memory than needed.++## [0.21.3]++### Added++* Parse errors now list possible expected tokens.++* Lexer errors now mention the file.++### Fixed++* Overloaded number literals cannot be sum types (#1557).++* Defective GPU code generation for vectorised non-commutative+  operatators (#1559).++* Excessive memory usage for some programs (#1325).++## [0.21.2]++### Added++* New functions: `reduce_by_index_2d`, `reduce_by_index_3d`.++* Manifests now contain compiler version information.++### Fixed++* Allocation insertion pass bug (#1546).++* An exotic bug involving TLS and dynamically loading code generated+  by the `multicore` backend.++* Unconstrained ambiguous types now default to `()` (#1552).  This+  should essentially never have any observable impact, except that+  more programs will type check.++* Double buffering compiler crash (#1553).++## [0.21.1]++### Added++* Top-level value definitions can (and should) now be declared with+  with `def`, although `let` still works.++* New tool: `futhark defs`, for printing locations of top-level+  definitions.++### Changed++* `def` is now a reserved word.++### Fixed++* Contrived intra-group code versions with no actual parallelism would+  be given a group size of zero (#1524).++## [0.20.8]++### Added++* `futhark repl` now allows Ctrl-c to interrupt execution.++### Fixed++* Alias tracking of sum types.++* Proper checking that a function declared to return a unique-typed+  value actually does so.++* Faulty uniqueness checking and inference for lambdas (#1535).++* Monomorphisation would duplicate functions under rare circumstances+  (#1537).++* Interpreter didn't check that the arguments passed to `unflatten`+  made sense (#1539).++* `futhark literate` now supports a `$loaddata` builtin function for+  passing datasets to Futhark programs.++## [0.20.7]++### Added++* Better exploitation of parallelism in fused nested segmented+  reductions.++* Prelude function `not` for negating booleans.++### Fixed++* Some incorrect removal of copies (#1505).++* Handling of parametric modules with top-level existentials (#1510).++* Module substitution fixes (#1512, #1518).++* Invalid in-place lowering (#1523).++* Incorrect code generation for some intra-group parallel code versions.++* Flattening crash in the presence of irregular parallelism (#1525).++* Incorrect substitution of type abbreviations with hidden sizes (#1531).++* Proper handling of NaN in `min`/`max` functions for+  `f16`/`f32`/`f64` in interpreter (#1528).++## [0.20.6]++### Added++* Much better code generation for segmented scans with vectorisable+  operators.++### Fixed++* Fixes to extremely exotic GPU scans involving array operators.++* Missing alias tracking led to invalid rewrites, causing a compiler+  crash (#1499).++* Top-level bindings with existential sizes were mishandled (#1500, #1501).++* A variety of memory leaks in the multicore backend, mostly (or+  perhaps exclusively) centered around context freeing or failing+  programs - this should not have affected many people.++* Various fixes to `f16` handling in the GPU backends.++## [0.20.5]++### Added++* Existential sizes can now be explicitly quantified in type+  expressions (#1308).++* Significantly expanded error index.++* Attributes can now be numeric.++* Patterns can now have attributes.  None have any effect at the+  moment.++* `futhark autotune` and `futhark bench` now take a `--spec-file`+  option for loading a test specification from another file.++### Fixed++* `auto output` reference datasets are now recreated when the program+  is newer than the data files.++* Exotic hoisting bug (#1490).++## [0.20.4]++### Added++* Tuning parameters now (officially) exposed in the C API.++* `futhark autotune` is now 2-3x faster on many programs, as it now+  keeps the process running.++* Negative numeric literals are now allowed in `case` patterns.++### Fixed++* `futhark_context_config_set_profiling` was missing for the `c` backend.++* Correct handling of nested entry points (#1478).++* Incorrect type information recorded when doing in-place lowering (#1481).++## [0.20.3]++### Added++* Executables produced by C backends now take a `--no-print-result` option.++* The C backends now generate a manifest when compiling with+  `--library`.  This can be used by FFI generators (#1465).++* The beginnings of a Rust-style error index.++* `scan` on newer CUDA devices is now much faster.++### Fixed++* Unique opaque types are named properly in entry points.++* The CUDA backend in library mode no longer `exit()`s the process if+  NVRTC initialisation fails.++## [0.20.2]++### Fixed++* Simplification bug (#1455).++* In-place-lowering bug (#1457).++* Another in-place-lowering bug (#1460).++* Don't try to tile inside loops with parameters with variant sizes (#1462).++* Don't consider it an ICE when the user passes invalid command line+  options (#1464).++## [0.20.1]++### Added++  * The `#[trace]` and `#[break]` attributes now replace the `trace`+    and `break` functions (although they are still present in+    slightly-reduced but compatible form).++  * The `#[opaque]` attribute replaces the `opaque` function, which is+    now deprecated.++  * Tracing now works in compiled code, albeit with several caveats+    (mainly, it does not work for code running on the GPU).++  * New `wasm` and `wasm-multicore` backends by Philip Lassen.  Still+    very experimental; do not expect API stability.++  * New intrinsic type `f16`, along with a prelude module `f16`.+    Implemented with hardware support where it is available, and with+    `f32`-based emulation where it is not.++  * Sometimes slightly more informative error message when input of+    the wrong type is passed to a test program.++### Changed++  * The `!` function in the integer modules is now called `not`.++  * `!` is now builtin syntax.  You can no longer define a function+    called `!`.  It is extremely unlikely this affects you.  This+    removes the last special-casing of prefix operators.++  * A prefix operator section (i.e. `(!)`) is no longer permitted+    (and it never was according to the grammar).++  * The offset parameter for the "raw" array creation functions in the+    C API is now `int64_t` instead of `int`.++### Fixed++  * `i64.abs` was wrong for arguments that did not fit in an `i32`.++  * Some `f32` operations (`**`, `abs`, `max`) would be done in double+    precision on the CUDA backend.++  * Yet another defunctorisation bug (#1397).++  * The `clz` function would sometimes exhibit undefined behaviour in+    CPU code (#1415).++  * Operator priority of prefix `-` was wrong - it is now the same as+    `!` (#1419).++  * `futhark hash` is now invariant to source location as well as+    stable across OS/compiler/library versions.++  * `futhark literate` is now much better at avoiding unnecessary+    recalculation.++  * Fixed a hole in size type checking that would usually lead to+    compiler crashes (#1435).++  * Underscores now allowed in numeric literals in test data (#1440).++  * The `cuda` backend did not use single-pass segmented scans as+    intended.  Now it does.++## [0.19.7]++### Added++  * A new memory reuse optimisation has been added.  This results in+    slightly lower footprint for many programs.++  * The `cuda` backend now uses a fast single-pass implementation for+    segmented `scan`s, due to Morten Tychsen Clausen (#1375).++  * `futhark bench` now prints interim results while it is running.++### Fixed++  * `futhark test` now provides better error message when asked to+    test an undefined entry point (#1367).++  * `futhark pkg` now detects some nonsensical package paths (#1364).++  * FutharkScript now parses `f x y` as applying `f` to `x` and `y`,+    rather than as `f (x y)`.++  * Some internal array utility functions would not be generated if+    entry points exposed both unit arrays and boolean arrays (#1374).++  * Nested reductions used (much) more memory for intermediate results+    than strictly needed.++  * Size propagation bug in defunctionalisation (#1384).++  * In the C FFI, array types used only internally to implement opaque+    types are no longer exposed (#1387).++  * `futhark bench` now copes with test programs that consume their+    input (#1386).  This required an extension of the server protocol+    as well.++## [0.19.6]++### Added++  * `f32.hypot` and `f64.hypot` are now much more numerically exact in+    the interpreter.++  * Generated code now contains a header with information about the+    version of Futhark used (and maybe more information in the+    future).++  * Testing/benchmarking with large input data (including randomly+    generated data) is much faster, as each file is now only read+    once.++  * Test programs may now use arbitrary FutharkScript expressions to+    produce test input, in particular expressions that produce opaque+    values.  This affects both testing, benchmarking, and autotuning.++  * Compilation is about 10% faster, especially for large programs.++### Fixed++  * `futhark repl` had trouble with declarations that produced unknown+    sizes (#1347).++  * Entry points can now have same name as (undocumented!) compiler intrinsics.++  * FutharkScript now detects too many arguments passed to functions.++  * Sequentialisation bug (#1350).++  * Missing causality check for index sections.++  * `futhark test` now reports mismatches using proper indexes (#1356).++  * Missing alias checking in fusion could lead to compiler crash (#1358).++  * The absolute value of NaN is no longer infinity in the interpreter (#1359).++  * Proper detection of zero strides in compiler (#1360).++  * Invalid memory accesses related to internal bookkeeping of bounds checking.++## [0.19.5]++### Added++  * Initial work on granting programmers more control over existential+    sizes, starting with making type abbreviations function as+    existential quantifiers (#1301).++  * FutharkScript now also supports arrays and scientific notation.++  * Added `f32.epsilon` and `f64.epsilon` for the difference between+    1.0 and the next larger representable number.++  * Added `f32.hypot` and `f64.hypot` for your hypothenuse needs (#1344).++  * Local size bindings in `let` expressions, e.g:++    ```+    let [n] (xs': [n]i32) = filter (>0) xs+    in ...+    ```++### Fixed++  * `futhark_context_report()` now internally calls+    `futhark_context_sync()` before collecting profiling information+    (if applicable).++  * `futhark literate`: Parse errors for expression directives now+    detected properly.++  * `futhark autotune` now works with the `cuda` backend (#1312).++  * Devious fusion bug (#1322) causing compiler crashes.++  * Memory expansion bug for certain complex GPU kernels (#1328).++  * Complex expressions in index sections (#1332).++  * Handling of sizes in abstract types in the interpreter (#1333).++  * Type checking of explicit size requirements in `loop` parameter (#1324).++  * Various alias checking bugs (#1300, #1340).++## [0.19.4]++### Fixed++  * Some uniqueness ignorance in fusion (#1291).++  * An invalid transformation could in rare cases cause race+    conditions (#1292).++  * Generated Python and C code should now be warning-free.++  * Missing check for uses of size-lifted types (#1294).++  * Error in simplification of concatenations could cause compiler+    crashes (#1296).++## [0.19.3]++### Added++  * Better `futhark test`/`futhark bench` errors when test data does+    not have the expected type.++### Fixed++  * Mismatch between how thresholds were printed and what the+    autotuner was looking for (#1269).++  * `zip` now produces unique arrays (#1271).++  * `futhark literate` no longer chokes on lines beginning with `--`+    without a following whitespace.++  * `futhark literate`: `:loadimg` was broken due to overzealous+    type checking (#1276).++  * `futhark literate`: `:loadimg` now handles relative paths properly.++  * `futhark hash` no longer considers the built-in prelude.++  * Server executables had broken store/restore commands for opaque types.++## [0.19.2]++### Added++  * New subcommand: `futhark hash`.++  * `futhark literate` is now smart about when to regenerate image and+    animation files.++  * `futhark literate` now produces better error messages passing+    expressions of the wrong type to directives.++### Fixed++  * Type-checking of higher-order functions that take consuming+    funtional arguments.++  * Missing cases in causality checking (#1263).++  * `f32.sgn` was mistakenly defined with double precision arithmetic.++  * Only include double-precision atomics if actually needed by+    program (this avoids problems on devices that only support single+    precision).++  * A lambda lifting bug due to not handling existential sizes+    produced by loops correctly (#1267).++  * Incorrect uniqueness attributes inserted by lambda lifting+    (#1268).++  * FutharkScript record expressions were a bit too sensitive to+    whitespace.++## [0.19.1]++### Added++  * `futhark literate` now supports a `$loadimg` builtin function for+    passing images to Futhark programs.++  * The `futhark literate` directive for generating videos is now+    `:video`.++  * Support for 64-bit atomics on CUDA and OpenCL for higher+    performance with `reduce_by_index` in particular.+    Double-precision float atomics are used on CUDA.++  * New functions: `f32.recip` and `f64.recip` for multiplicative inverses.++  * Executables produced with the `c` and `multicore` backends now+    also accept `--tuning` and `--size` options (although there are+    not yet any tunable sizes).++  * New functions: `scatter_2d` and `scatter_3d` for scattering to+    multi-dimensional arrays (#1258).++### Removed++  * The math modules no longer define the name `negate` (use `neg`+    instead).++### Fixed++  * Exotic core language alias tracking bug (#1239).++  * Issue with entry points returning constant arrays (#1240).++  * Overzealous CSE collided with uniqueness types (#1241).++  * Defunctionalisation issue (#1242).++  * Tiling inside multiply nested loops (#1243).++  * Substitution bug in interpreter (#1250).++  * `f32.sgn`/`f64.sgn` now correct for NaN arguments.++  * CPU backends (`c`/`multicore`) are now more careful about staying+    in single precision for `f32` functions (#1253).++  * `futhark test` and `futhark bench` now detect program+    initialisation errors in a saner way (#1246).++  * Partial application of operators with parameters used in a+    size-dependent way now works (#1256).++  * An issue regarding abstract size-lifted sum types (#1260).++## [0.18.6]++### Added++  * The C API now exposes serialisation functions for opaque values.++  * The C API now lets you pick which stream (if any) is used for+    logging prints (#1214).++  * New compilation mode: `--server`.  For now used to support faster+    benchmarking and testing tools, but can be used to build even+    fancier things in the future (#1179).++  * Significantly faster reading/writing of large values.  This mainly+    means that validation of test and benchmark results is much faster+    (close to an order of magnitude).++  * The experimental `futhark literate` command allows vaguely a+    notebook-like programming experience.++  * All compilers now accept an `--entry` option for treating more+    functions as entry points.++  * The `negate` function is now `neg`, but `negate` is kept around+    for a short while for backwards compatibility.++  * Generated header-files are now declared `extern "C"` when+    processed with a C++ compiler.++  * Parser errors in test blocks used by `futhark bench` and `futhark+    test` are now reported with much better error messages.++### Fixed++  * Interaction between slice simplification and in-place updates+    (#1222).++  * Problem with user-defined functions with the same name as intrinsics.++  * Names from transitive imports no longer leak into scope (#1231).++  * Pattern-matching unit values now works (#1232).++## [0.18.5]++### Fixed++  * Fix tiling crash (#1203).++  * `futhark run` now does slightly more type-checking of its inputs+    (#1208).++  * Sum type deduplication issue (#1209).++  * Missing parentheses when printing sum values in interpreter.++## [0.18.4]++### Added++  * When compiling to binaries in the C-based backends, the compiler+    now respects the ``CFLAGS`` and ``CC`` environment variables.++  * GPU backends: avoid some bounds-checks for parallel sections+    inside intra-kernel loops.++  * The `cuda` backend now uses a much faster single-pass `scan`+    implementation, although only for nonsegmented scans where the+    operator operates on scalars.++### Fixed++  * `futhark dataset` now correctly detects trailing commas in textual+    input (#1189).++  * Fixed local memory capacity check for intra-group-parallel GPU kernels.++  * Fixed compiler bug on segmented rotates where the rotation amount+    is variant to the nest (#1192).++  * `futhark repl` no longer crashes on type errors in given file (#1193).++  * Fixed a simplification error for certain arithmetic expressions+    (#1194).++  * Fixed a small uniqueness-related bug in the compilation of+    operator section.++  * Sizes of opaque entry point arguments are now properly checked+    (related to #1198).++## [0.18.3]++### Fixed++  * Python backend now disables spurious NumPy overflow warnings for+    both library and binary code (#1180).++  * Undid deadlocking over-synchronisation for freeing opaque objects.++  * `futhark datacmp` now handles bad input files better (#1181).++## [0.18.2]++### Added++  * The GPU loop tiler can now handle loops where only a subset of the+    input arrays are tiled.  Matrix-vector multiplication is one+    important program where this helps (#1145).++  * The number of threads used by the `multicore` backend is now+    configurable (`--num-threads` and+    `futhark_context_config_set_num_threads()`). (#1162)++### Fixed++  * PyOpenCL backend would mistakenly still streat entry point+    argument sizes as 32 bit.++  * Warnings are now reported even for programs with type errors.++  * Multicore backend now works properly for very large iteration+    spaces.++  * A few internal generated functions (`init_constants()`,+    `free_constants()`) were mistakenly declared non-static.++  * Process exit code is now nonzero when compiler bugs and+    limitations are encountered.++  * Multicore backend crashed on `reduce_by_index` with nonempty target+    and empty input.++  * Fixed a flattening issue for certain complex `map` nestings+    (#1168).++  * Made API function `futhark_context_clear_caches()` thread safe+    (#1169).++  * API functions for freeing opaque objects are now thread-safe+    (#1169).++  * Tools such as `futhark dataset` no longer crash with an internal+    error if writing to a broken pipe (but they will return a nonzero+    exit code).++  * Defunctionalisation had a name shadowing issue that would crop up+    for programs making very advanced use of functional+    representations (#1174).++  * Type checker erroneously permitted pattern-matching on string+    literals (this would fail later in the compiler).++  * New coverage checker for pattern matching, which is more correct.+    However, it may not provide quite as nice counter-examples+    (#1134).++  * Fix rare internalisation error (#1177).++## [0.18.1]++### Added++  * Experimental multi-threaded CPU backend, `multicore`.++### Changed++  * All sizes are now of type `i64`.  This has wide-ranging+    implications and most programs will need to be updated (#134).++## [0.17.3]++### Added++  * Improved parallelisation of `futhark bench` compilation.++### Fixed++  * Dataset generation for test programs now use the right `futhark`+    executable (#1133).++  * Really fix NaN comparisons in interpreter (#1070, again).++  * Fix entry points with a parameter that is a sum type where+    multiple constructors contain arrays of the same statically known+    size.++  * Fix in monomorphisation of types with constant sizes.++  * Fix in in-place lowering (#1142).++  * Fix tiling inside multiple nested loops (#1143).++## [0.17.2]++### Added++  * Obscure loop optimisation (#1110).++  * Faster matrix transposition in C backend.++  * Library code generated with CUDA backend can now be called from+    multiple threads.++  * Better optimisation of concatenations of array literals and+    replicates.++  * Array creation C API functions now accept `const` pointers.++  * Arrays can now be indexed (but not sliced) with any signed integer+    type (#1122).++  * Added --list-devices command to OpenCL binaries (#1131)++  * Added --help command to C, CUDA and OpenCL binaries (#1131)++### Removed++  * The integer modules no longer contain `iota` and `replicate`+    functions.  The top-level ones still exist.++  * The `size` module type has been removed from the prelude.++### Changed++  * Range literals may no longer be produced from unsigned integers.++### Fixed++  * Entry points with names that are not valid C (or Python)+    identifiers are now pointed out as problematic, rather than+    generating invalid C code.++  * Exotic tiling bug (#1112).++  * Missing synchronisation for in-place updates at group level.++  * Fixed (in a hacky way) an issue where `reduce_by_index` would use+    too much local memory on AMD GPUs when using the OpenCL backend.++## [0.16.4]++### Added++  * `#[unroll]` attribute.++  * Better error message when writing `a[i][j]` (#1095).++  * Better error message when missing "in" (#1091).++### Fixed++  * Fixed compiler crash on certain patterns of nested parallelism+    (#1068, #1069).++  * NaN comparisons are now done properly in interpreter (#1070).++  * Fix incorrect movement of array indexing into branches `if`s+    (#1073).++  * Fix defunctorisation bug (#1088).++  * Fix issue where loop tiling might generate out-of-bounds reads+    (#1094).++  * Scans of empty arrays no longer result in out-of-bounds memory+    reads.++  * Fix yet another defunctionalisation bug due to missing+    eta-expansion (#1100).++## [0.16.3]++### Added++  * `random` input blocks for `futhark test` and `futhark bench` now+    support floating-point literals, which must always have either an+    `f32` or `f64` suffix.++  * The `cuda` backend now supports the `-d` option for executables.++  * The integer modules now contain a `ctz` function for counting+    trailing zeroes.++### Fixed++  * The `pyopencl` backend now works with OpenCL devices that have+    multiple types (most importantly, oclgrind).++  * Fix barrier divergence when generating code for group-level+    colletive copies in GPU backend.++  * Intra-group flattening now looks properly inside of branches.++  * Intra-group flattened code versions are no longer used when the+    resulting workgroups would have less than 32 threads (with default+    thresholds anyway) (#1064).++## [0.16.2]++### Added++  * `futhark autotune`: added `--pass-option`.++### Fixed++  * `futhark bench`: progress bar now correct when number of runs is+    less than 10 (#1050).++  * Aliases of arguments passed for consuming parameters are now+    properly checked (#1053).++  * When using a GPU backend, errors are now properly cleared.+    Previously, once e.g. an out-of-bounds error had occurred, all+    future operations would fail with the same error.++  * Size-coercing a transposed array no longer leads to invalid code+    generation (#1054).++## [0.16.1]++### Added++  * Incremental flattening is now performed by default.  Use+    attributes to constrain and direct the flattening if you have+    exotic needs.  This will likely need further iteration and+    refinement.++  * Better code generation for `reverse` (and the equivalent explicit+    slice).++  * `futhark bench` now prints progress bars.++  * The `cuda` backend now supports similar profiling as the `opencl`+    option, although it is likely slightly less accurate in the+    presence of concurrent operations.++  * A preprocessor macro `FUTHARK_BACKEND_foo` is now defined in+    generated header files, where *foo* is the name of the backend+    used.++  * Non-inlined functions (via `#[noinline]`) are now supported in GPU+    code, but only for functions that *exclusively* operate on+    scalars.++  * `futhark repl` now accepts a command line argument to load a+    program initially.++  * Attributes are now also permitted on declarations and specs.++  * `futhark repl` now has a `:nanbreak` command (#839).++### Removed++  * The C# backend has been removed (#984).++  * The `unsafe` keyword has been removed.  Use `#[unsafe]` instead.++### Changed++  * Out-of-bounds literals are now an error rather than a warning.++  * Type ascriptions on entry points now always result in opaque types+    when the underlying concrete type is a tuple (#1048).++### Fixed++  * Fix bug in slice simplification (#992).++  * Fixed a typer checker bug for tracking the aliases of closures+    (#995).++  * Fixed handling of dumb terminals in futhark test (#1000).++  * Fixed exotic monomorphisation case involving lifted type+    parameters instantiated with functions that take named parameters+    (#1026).++  * Further tightening of the causality restriction (#1042).++  * Fixed alias tracking for right-operand operator sections (#1043).++## [0.15.8]++### Added+++  * Warnings for overflowing literals, such as `1000 : u8`.++  * Futhark now supports an attribute system, whereby expressions can+    be tagged with attributes that provide hints or directions to the+    compiler.  This is an expert-level feature, but it is sometimes+    useful.++## [0.15.7]++### Added++  * Faster index calculations for very tight GPU kernels (such as the+    ones corresponding to 2D tiling).++  * `scan` with vectorised operators (e.g. `map2 (+)`) is now faster+    in some cases.++  * The C API has now been documented and stabilized, including+    obtaining profiling information (although this is still+    unstructured).++### Fixed++  * Fixed some cases of missing fusion (#953).++  * Context deinitialisation is now more complete, and should not leak+    memory (or at least not nearly as much, if any).  This makes it+    viable to repeatedly create and free Futhark contexts in the same+    process (although this can still be quite slow).++## [0.15.6]++### Added++  * Binary operators now act as left-to-right sequence points with+    respect to size types.++  * `futhark bench` now has more colourful and hopefully readable+    output.++  * The compiler is now about 30% faster for most nontrivial programs.+    This is due to parallelising the inlining stage, and tweaking the+    default configuration of the Haskell RTS.++  * `futhark dataset` is now about 8-10x faster.++### Fixed++  * Fixed some errors regarding constants (#941).++  * Fixed a few missing type checker cases for sum types (#938).++  * Fix OOB write in CUDA backend runtime code (#950).++## [0.15.5]++### Added++  * `reduce_by_index` with `f32`-addition is now approximately 2x+    faster in the CUDA backend.++### Fixed++  * Fixed kernel extractor bug in `if`-interchange (#921).++  * Fixed some cases of malformed kernel code generation (#922).++  * Fixed rare memory corruption bug involving branches returning+    arrays (#923).++  * Fixed spurious warning about entry points involving opaque return+    types, where the type annotations are put on a higher-order return+    type.++  * Fixed incorrect size type checking for sum types in negative+    position with unknown constructors (#927).++  * Fixed loop interchange for permuted sequential loops with more+    than one outer parallel loop (#928).++  * Fixed a type checking bug for branches returning incomplete sum+    types (#931).++## [0.15.4]++### Added++  * `futhark pkg` now shells out to `curl` for HTTP requests.++  * `futhark doc` now supports proper GitHub-flavored Markdown, as it+    uses the `cmark-gfm` library internally.++  * Top-level constants are now executed only once per program+    instance.  This matters when Futhark is used to generate library+    code.++  * `futhark autotune` is better at handling degrees of parallelism+    that assume multiple magnitudes during a single run.++  * `futhark pkg` now uses `curl` to retrieve packages.++  * Type errors are now printed in red for better legibility (thanks+    to @mxxo!).++### Fixed++  * Fixed incorrect handling of opaques in entry point return types.++  * `futhark pkg` now works properly with GitLab (#899).++## [0.15.3]++### Added++  * `scan` now supports operators whose operands are arrays.  They are+    significantly slower than primitive-typed scans, so avoid them if+    at all possible.++  * Precomputed constants are now handled much more efficiently.++  * Certain large programs that rely heavily on inlining now compile+    orders of magnitude faster.++### Fixed++  * Some fixes to complicated module expressions.++  * `futhark pkg` should no longer crash uncontrollably on network+    errors (#894).++  * Fixed local open in interpreter (#887).++  * Fix error regarding entry points that called other entry points+    which contained local functions (#895).++  * Fix loading OpenCL kernels from a binary.++## [0.15.2]++### Fixed++  * Fix a REPL regression that made it unable to handle overloaded+    types (such as numeric literals, oops).++  * The uniqueness of a record is now the minimum of the uniqueness of+    any of its elements (#870).++  * Bug in causality checking has been fixed (#872).++  * Invariant memory allocations in scan/reduce operators are now supported.++  * `futhark run` now performs more type checking on entry point input (#876).++  * Compiled Futhark programs now check for EOF after the last input+    argument has been read (#877).++  * Fixed a bug in `loop` type checking that prevented the result from+    ever aliasing the initial parameter values (#879).++## [0.15.1]++### Added++  * Futhark now type-checks size annotations using a size-dependent+    type system.++  * The parallel code generators can now handle bounds checking and+    other safety checks.++  * Integer division by zero is now properly safety-checked and+    produces an error message.++  * Integer exponentiation with negative exponent is now properly+    safety-checked and produces an error message.++  * Serious effort has been put into improving type errors.++  * `reduce_by_index` may be somewhat faster for complex operators on+    histograms that barely fit in local memory.++  * Improved handling of in-place updates of multidimensional arrays+    nested in `map`.  These are now properly parallelised.++  * Added `concat_to` and `flatten_to` functions to prelude.++  * Added `indices` function to the prelude.++  * `futhark check` and all compilers now take a `-w` option for+    disabling warnings.++  * `futhark bench` now accepts `--pass-compiler-option`.++  * The integer modules now have `mad_hi` and `mul_hi` functions for+    getting the upper part of multiplications.  Thanks to @porcuquine+    for the contribution!++  * The `f32` and `f64` modules now also define `sinh`, `cosh`,+    `tanh`, `asinh`, `acosh`, and `atanh` functions.++  * The `f32` and `f64` modules now also define `fma` and `mad`+    functions.++### Removed++  * Removed `update`, `split2`, `intersperse`, `intercalate`, `pick`,+    `steps`, and `range` from the prelude.++### Changed++  * `"futlib"` is now called `"prelude"`, and it is now an error to+    import it explicitly.++### Fixed++  * Corrected address calculations in `csharp` backend.++  * The C backends are now more careful about generating overflowing+    integer operations (since this is undefined behaviour in C, but+    defined in Futhark).++  * `futhark dataset` no longer crashes uncontrollably when used+    incorrectly (#849).++## [0.14.1]++### Added++  * The optimiser is now somewhat better at removing unnecessary+    copies of array slices.++  * `futhark bench` and `futhark test` now take a `--concurrency`+    option for limiting how many threads are used for housekeeping+    tasks.  Set this to a low value if you run out of memory.++  * `random` test blocks are now allowed to contain integer literals+    with type suffixes.++  * `:frame <n>` command for `futhark repl` for inspecting the stack.++  * `e :> t` notation, which means the same as `e : t` for now, but+    will have looser constraints in the future.++  * Size-lifted type abbreviations can be declared with `type~` and+    size-lifted type parameters with `'~`.  These currently have no+    significant difference from fully lifted types.++### Changed++  * Tuples are now 0-indexed (#821, which also includes a conversion+    script).++  * Invalid ranges like `1..<0` now produce a run-time error instead+    of an empty array.++  * Record updates (`r with f = e`) now require `r` to have a+    completely known type up to `f`.  This is a restriction that will+    hopefully be lifted in the future.++  * The backtrace format has changed to be innermost-first, like+    pretty much all other languages.++  * Value specs must now explicitly quantify all sizes of function+    parameters.  Instead of++        val sum: []t -> t++    you must write++        val sum [n]: [n]t -> t++  * `futhark test` now once again numbers un-named data sets from 0+    rather than from 1.  This fits a new general principle of always+    numbering from 0 in Futhark.++  * Type abbreviations declared with `type` may no longer contain+    functions or anonymous sizes in their definition.  Use `type^` for+    these cases.  Just a warning for now, but will be an error in the+    future.++### Fixed++  * Work around (probable) AMD OpenCL compiler bug for+    `reduce_by_index` operations with complex operators that require+    locking.++  * Properly handle another ICE on parse errors in test stanzas (#819).++  * `futhark_context_new_with_command_queue()` now actually works.  Oops.++  * Different scopes are now properly addressed during type inference+    (#838).  Realistically, there will still be some missing cases.++## [0.13.2]++### Added++  * New subcommand, `futhark query`, for looking up information about+    the name at some position in a file.  Intended for editor+    integration.++  * (Finally) automatic support for compute model 7.5 in the CUDA backend.++  * Somewhat better performance for very large target arrays for+    `reduce_by_index.`.++### Fixed++  * Fixed a slice-iota simplification bug (#813).++  * Fixed defunctionalisation crash involving intrinsics (#814).++## [0.13.1]++### Added++  * Stack traces are now multiline for better legibility.++### Changed++  * The `empty(t)` notation now specifies the type of the *entire+    value* (not just the element type), and requires dimension sizes+    when `t` is an array (e.g. `empty(i32)` is no longer allowed, you+    need for example `empty([0]i32)`).++  * All input files are now assumed to be in UTF-8.++### Fixed++  * Fixed exponential-time behaviour for certain kernels with large+    arithmetic expressions (#805).++  * `futhark test` and friends no longer crash when reporting some+    errors (#808).++  * Fix uniqueness of loop results (#810).++## [0.12.3]++### Added++  * Character literals can now be any integer type.++  * The integer modules now have `popc` and `clz` functions.++  * Tweaked inlining so that larger programs may now compile faster+    (observed about 20%).++  * Pattern-matching on large sum typed-values taken from arrays may+    be a bit faster.++### Fixed++  * Various small fixes to type errors.++  * All internal functions used in generated C code are now properly+    declared `static`.++  * Fixed bugs when handling dimensions and aliases in type ascriptions.++## [0.12.2]++### Added++  * New tool: `futhark autotune`, for tuning the threshold parameters+    used by incremental flattening.  Based on work by Svend Lund+    Breddam, Simon Rotendahl, and Carl Mathias Graae Larsen.++  * New tool: `futhark dataget`, for extracting test input data.  Most+    will probably never use this.++  * Programs compiled with the `cuda` backend now take options+    `--default-group-size`, `--default-num-groups`, and+    `--default-tile-size`.++  * Segmented `reduce_by_index` are now substantially fasted for small+    histograms.++  * New functions: `f32.lerp` and `f64.lerp`, for linear interpolation.++### Fixed++  * Fixes to aliasing of record updates.++  * Fixed unnecessary array duplicates after coalescing optimisations.++  * `reduce_by_index` nested in `map`s will no longer sometimes+    require huge amounts of memory.++  * Source location now correct for unknown infix operators.++  * Function parameters are no longer in scope of themselves (#798).++  * Fixed a nasty out-of-bounds error in handling of irregular allocations.++  * The `floor`/`ceil` functions in `f32`/`f64` now handle infinities+    correctly (and are also faster).++  * Using `%` on floats now computes fmod instead of crashing the compiler.++## [0.12.1]++### Added++  * The internal representation of parallel constructs has been+    overhauled and many optimisations rewritten.  The overall+    performance impact should be neutral on aggregate, but there may+    be changes for some programs (please report if so).++  * Futhark now supports structurally typed sum types and pattern+    matching!  This work was done by Robert Schenck.  There remain+    some problems with arrays of sum types that themselves contain+    arrays.++  * Significant reduction in compile time for some large programs.++  * Manually specified type parameters need no longer be exhaustive.++  * Mapped `rotate` is now simplified better.  This can be+    particularly helpful for stencils with wraparound.++### Removed++  * The `~` prefix operator has been removed.  `!` has been extended+    to perform bitwise negation when applied to integers.++### Changed++  * The `--futhark` option for `futhark bench` and `futhark test` now+    defaults to the binary being used for the subcommands themselves.++  * The legacy `futhark -t` option (which did the same as `futhark+    check`) has been removed.++  * Lambdas now bind less tightly than type ascription.++  * `stream_map` is now `map_stream` and `stream_red` is now+    `reduce_stream`.++### Fixed++  * `futhark test` now understands `--no-tuning` as it was always+    supposed to.++  * `futhark bench` and `futhark test` now interpret `--exclude` in+    the same way.++  * The Python and C# backends can now properly read binary boolean+    input.++## [0.11.2]++### Fixed++  * Entry points whose types are opaque due to module ascription, yet+    whose representation is simple (scalars or arrays of scalars) were+    mistakely made non-opaque when compiled with ``--library``.  This+    has been fixed.++  * The CUDA backend now supports default sizes in `.tuning` files.++  * Loop interchange across multiple dimensions was broken in some cases (#767).++  * The sequential C# backend now generates code that compiles (#772).++  * The sequential Python backend now generates code that runs (#765).++## [0.11.1]++### Added++  * Segmented scans are a good bit faster.++  * `reduce_by_index` has received a new implementation that uses+    local memory, and is now often a good bit faster when the target+    array is not too large.++  * The `f32` and `f64` modules now contain `gamma` and `lgamma`+    functions.  At present these do not work in the C# backend.++  * Some instances of `reduce` with vectorised operators (e.g. `map2+    (+)`) are orders of magnitude faster than before.++  * Memory usage is now lower on some programs (specifically the ones+    that have large `map`s with internal intermediate arrays).++### Removed++  * Size *parameters* (not *annotations*) are no longer permitted+    directly in `let` and `loop` bindings, nor in lambdas.  You are+    likely not affected (except for the `stream` constructs; see+    below).  Few people used this.++### Changed++  * The array creation functions exported by generated C code now take+    `int64_t` arguments for the shape, rather than `int`.  This is in+    line with what the shape functions return.++  * The types for `stream_map`, `stream_map_per`, `stream_red`, and+    `stream_red_per` have been changed, such that the chunk function+    now takes the chunk size as the first argument.++### Fixed++  * Fixes to reading values under Python 3.++  * The type of a variable can now be deduced from its use as a size+    annotation.++  * The code generated by the C-based backends is now also compilable+    as C++.++  * Fix memory corruption bug that would occur on very large segmented+    reductions (large segments, and many of them).++## [0.10.2]++### Added++  * `reduce_by_index` is now a good bit faster on operators whose+    arguments are two 32-bit values.++  * The type checker warns on size annotations for function parameters+    and return types that will not be visible from the outside,+    because they refer to names nested inside tuples or records.  For+    example, the function++        let f (n: i32, m: i32): [n][m]i32 = ...++    will cause such a warning.  It should instead be written++        let f (n: i32) (m: i32): [n][m]i32 = ...++  * A new library function+    `futhark_context_config_select_device_interactively()` has been+    added.++### Fixed++  * Fix reading and writing of binary files for C-compiled executables+    on Windows.++  * Fixed a couple of overly strict internal sanity checks related to+    in-place updates (#735, #736).++  * Fixed a couple of convoluted defunctorisation bugs (#739).++## [0.10.1]++### Added++  * Using definitions from the `intrinsic` module outside the prelude+    now results in a warning.++  * `reduce_by_index` with vectorised operators (e.g. `map2 (+)`) is+    orders of magnitude faster than before.++  * Executables generated with the `pyopencl` backend now support the+    options `--default-tile-size`, `--default-group-size`,+    `--default-num-groups`, `--default-threshold`, and `--size`.++  * Executables generated with `c` and `opencl` now print a help text+    if run with invalid options.  The `py` and `pyopencl` backends+    already did this.++  * Generated executables now support a `--tuning` flag for passing+    many tuned sizes in a file.++  * Executables generated with the `cuda` backend now take an+    `--nvrtc-option` option.++  * Executables generated with the `opencl` backend now take a+    `--build-option` option.++### Removed++  * The old `futhark-*` executables have been removed.++### Changed++  * If an array is passed for a function parameter of a polymorphic+    type, all arrays passed for parameters of that type must have the+    same shape.  For example, given a function++        let pair 't (x: t) (y: t) = (x, y)++    The application `pair [1] [2,3]` will now fail at run-time.++  * `futhark test` now numbers un-named data sets from 1 rather than+    0.  This only affects the text output and the generated JSON+    files, and fits the tuple element ordering in Futhark.++  * String literals are now of type `[]u8` and contain UTF-8 encoded+    bytes.++### Fixed++  * An significant problematic interaction between empty arrays and+    inner size declarations has been closed (#714).  This follows a+    range of lesser empty-array fixes from 0.9.1.++  * `futhark datacmp` now prints to stdout, not stderr.++  * Fixed a major potential out-of-bounds access when sequentialising+    `reduce_by_index` (in most cases the bug was hidden by subsequent+    C compiler optimisations).++  * The result of an anonymous function is now also forbidden from+    aliasing a global variable, just as with named functions.++  * Parallel scans now work correctly when using a CPU OpenCL+    implementation.++  * `reduce_by_index` was broken on newer NVIDIA GPUs when using fancy+    operators.  This has been fixed.++## [0.9.1]++### Added++  * `futhark cuda`: a new CUDA backend by Jakob Stokholm Bertelsen.++  * New command for comparing data files: `futhark datacmp`.++  * An `:mtype` command for `futhark repl` that shows the type of a+    module expression.++  * `futhark run` takes a `-w` option for disabling warnings.++### Changed++  * Major command reorganisation: all Futhark programs have been+    combined into a single all-powerful `futhark` program.  Instead of+    e.g. `futhark-foo`, use `futhark foo`.  Wrappers will be kept+    around under the old names for a little while.  `futharki` has+    been split into two commands: `futhark repl` and `futhark run`.+    Also, `py` has become `python` and `cs` has become `csharp`, but+    `pyopencl` and `csopencl` have remained as they were.++  * The result of a function is now forbidden from aliasing a global+    variable.  Surprisingly little code is affected by this.++  * A global definition may not be ascribed a unique type.  This never+    had any effect in the first place, but now the compiler will+    explicitly complain.++  * Source spans are now printed in a slightly different format, with+    ending the line number omitted when it is the same as the start+    line number.++### Fixed++  * `futharki` now reports source locations of `trace` expressions+    properly.++  * The type checker now properly complains if you try to define a+    type abbreviation that has unused size parameters.++## [0.8.1]++### Added++  * Now warns when `/futlib/...` files are redundantly imported.++  * `futharki` now prints warnings for files that are ":load"ed.++  * The compiler now warns when entry points are declared with types+    that will become unnamed and opaque, and thus impossible to+    provide from the outside.++  * Type variables invented by the type checker will now have a+    unicode subscript to distinguish them from type parameters+    originating in the source code.++  * `futhark-test` and `futhark-bench` now support generating random+    test data.++  * The library backends now generate proper names for arrays of+    opaque values.++  * The parser now permits empty programs.++  * Most transpositions are now a good bit faster, especially on+    NVIDIA GPUs.++### Removed++  * The `<-` symbol can no longer be used for in-place updates and+    record updates (deprecated in 0.7.3).++### Changed++  * Entry points that accept a single tuple-typed parameter are no+    longer silently rewritten to accept multiple parameters.++### Fixed++  * The `:type` command in `futharki` can now handle polymorphic+    expressions (#669).++  * Fixed serious bug related to chaining record updates.++  * Fixed type inference of record fields (#677).++  * `futharki` no longer goes in an infinite loop if a ``for`` loop+    contains a negative upper bound.++  * Overloaded number types can no longer carry aliases (#682).++## [0.7.4]++### Added++  * Support type parameters for operator specs defined with `val`.++### Fixed++  * Fixed nasty defunctionalisation bug (#661).++  * `cabal sdist` and `stack sdist` works now.++## [0.7.3]++### Added++  * Significant performance changes: there is now a constant extra+    compilation overhead (less than 200ms on most machines).  However,+    the rest of the compiler is 30-40% faster (or more in some cases).++  * A warning when ambiguously typed expressions are assigned a+    default (`i32` or `f64`).++  * In-place updates and record updates are now written with `=`+    instead of `<-`.  The latter is deprecated and will be removed in+    the next major version (#650).++### Fixed++  * Polymorphic value bindings now work properly with module type+    ascription.++  * The type checker no longer requires types used inside local+    functions to be unambiguous at the point where the local function+    is defined.  They must still be unambiguous by the time the+    top-level function ends.  This is similar to what other ML+    languages do.++  * `futhark-bench` now writes "μs" instead of "us".++  * Type inference for infix operators now works properly.++## [0.7.2]++### Added++  * `futhark-pkg` now supports GitLab.++  * `futhark-test`s `--notty` option now has a `--no-terminal` alias.+    `--notty` is deprecated, but still works.++  * `futhark-test` now supports multiple entry points per test block.++  * Functional record updates: `r with f <- x`.++### Fixed++  * Fix the `-C` option for `futhark-test`.++  * Fixed incorrect type of `reduce_by_index`.++  * Segmented `reduce_by_index` now uses much less memory.++## [0.7.1]++### Added++  * C# backend by Mikkel Storgaard Knudsen (`futhark-cs`/`futhark-csopencl`).++  * `futhark-test` and `futhark-bench` now take a `--runner` option.++  * `futharki` now uses a new interpreter that directly interprets the+    source language, rather than operating on the desugared core+    language.  In practice, this means that the interactive mode is+    better, but that interpretation is also much slower.++  * A `trace` function that is semantically `id`, but makes `futharki`+    print out the value.++  * A `break` function that is semantically `id`, but makes `futharki`+    stop and provide the opportunity to inspect variables in scope.++  * A new SOAC, `reduce_by_index`, for expressing generalised+    reductions (sometimes called histograms).  Designed and+    implemented by Sune Hellfritzsch.++### Removed++  * Most of futlib has been removed.  Use external packages instead:++    * `futlib/colour` => https://github.com/athas/matte++    * `futlib/complex` => https://github.com/diku-dk/complex++    * `futlib/date` => https://github.com/diku-dk/date++    * `futlib/fft` => https://github.com/diku-dk/fft++    * `futlib/linalg` => https://github.com/diku-dk/fft++    * `futlib/merge_sort`, `futlib/radix_sort` => https://github.com/diku-dk/sorts++    * `futlib/random` => https://github.com/diku-dk/cpprandom++    * `futlib/segmented` => https://github.com/diku-dk/segmented++    * `futlib/sobol` => https://github.com/diku-dk/sobol++    * `futlib/vector` => https://github.com/athas/vector++    No replacement: `futlib/mss`, `futlib/lss`.++  * `zip6`/`zip7`/`zip8` and their `unzip` variants have been removed.+    If you build gigantic tuples, you're on your own.++  * The `>>>` operator has been removed.  Use an unsigned integer type+    if you want zero-extended right shifts.++### Changed++  * The `largest`/`smallest` values for numeric modules have been+    renamed `highest`/`lowest`.++### Fixed++  * Many small things.++## [0.6.3]++### Added++  * Added a package manager: `futhark-pkg`.  See also [the+    documentation](http://futhark.readthedocs.io/en/latest/package-management.html).++  * Added `log2` and `log10` functions to `f32` and `f64`.++  * Module type refinement (`with`) now permits refining parametric+    types.++  * Better error message when invalid values are passed to generated+    Python entry points.++  * `futhark-doc` now ignores files whose doc comment is the word+    "ignore".++  * `copy` now works on values of any type, not just arrays.++  * Better type inference for array indexing.++### Fixed++  * Floating-point numbers are now correctly rounded to nearest even+    integer, even in exotic cases (#377).++  * Fixed a nasty bug in the type checking of calls to consuming+    functions (#596).++## [0.6.2]++### Added++  * Bounds checking errors now show the erroneous index and the size+    of the indexed array.  Some other size-related errors also show+    more information, but it will be a while before they are all+    converted (and say something useful - it's not entirely+    straightforward).++  * Opaque types now have significantly more readable names,+    especially if you add manual size annotations to the entry point+    definitions.++  * Backticked infix operators can now be used in operator sections.++### Fixed++  * `f64.e` is no longer pi.++  * Generated C library code will no longer `abort()` on application+    errors (#584).++  * Fix file imports on Windows.++  * `futhark-c` and `futhark-opencl` now generates thread-safe code (#586).++  * Significantly better behaviour in OOM situations.++  * Fixed an unsound interaction between in-place updates and+    parametric polymorphism (#589).++## [0.6.1]++### Added++  * The `real` module type now specifies `tan`.++  * `futharki` now supports entering declarations.++  * `futharki` now supports a `:type` command (or `:t` for short).++  * `futhark-test` and `futhark-benchmark` now support gzipped data+    files.  They must have a `.gz` extension.++  * Generated code now frees memory much earlier, which can help+    reduce the footprint.++  * Compilers now accept a `--safe` flag to make them ignore `unsafe`.++  * Module types may now define *lifted* abstract types, using the+    notation `type ^t`.  These may be instantiated with functional+    types.  A lifted abstract type has all the same restrictions as a+    lifted type parameter.++### Removed++  * The `rearrange` construct has been removed.  Use `transpose` instead.++  * `futhark-mode.el` has been moved to a [separate+    repository](https://github.com/diku-dk/futhark-mode).++  * Removed `|>>` and `<<|`.  Use `>->` and `<-<` instead.++  * The `empty` construct is no longer supported.  Just use empty+    array literals.++### Changed++  * Imports of the basis library must now use an absolute path+    (e.g. `/futlib/fft`, not simply `futlib/fft`).++  * `/futlib/vec2` and `/futlib/vec3` have been replaced by a new+    `/futlib/vector` file.++  * Entry points generated by the C code backend are now prefixed with+    `futhark_entry_` rather than just `futhark_`.++  * `zip` and `unzip` are no longer language constructs, but library+    functions, and work only on two arrays and pairs, respectively.+    Use functions `zipN/unzipN` (for `2<=n<=8`).++### Fixed++  * Better error message on EOF.++  * Fixed handling of `..` in `import` paths.++  * Type errors (and other compiler feedback) will no longer contain+    internal names.++  * `futhark-test` and friends can now cope with infinities and NaNs.+    Such values are printed and read as `f32.nan`, `f32.inf`,+    `-f32.inf`, and similarly for `f32`.  In `futhark-test`, NaNs+    compare equal.++## [0.5.2]++### Added++  * Array index section: `(.[i])` is shorthand for `(\x -> x[i])`.+    Full slice syntax supported. (#559)++  * New `assert` construct. (#464)++  * `futhark-mode.el` now contains a definition for flycheck.++### Fixed++  * The index produced by `futhark-doc` now contains correct links.++  * Windows linebreaks are now fully supported for test files (#558).++## [0.5.1]++### Added++  * Entry points need no longer be syntactically first-order.++  * Added overloaded numeric literals (#532).  This means type+    suffixes are rarely required.++  * Binary and unary operators may now be bound in patterns by+    enclosing them in parenthesis.++  * `futhark-doc` now produces much nicer documentation.  Markdown is+    now supported in documentation comments.++  * `/futlib/functional` now has operators `>->` and `<-<` for+    function composition.  `<<|` are `|>>` are deprecated.++  * `/futlib/segmented` now has a `segmented_reduce`.++  * Scans and reductions can now be horizontally fused.++  * `futhark-bench` now supports multiple entry points, just like+    `futhark-test`.++  * ".." is now supported in `include` paths.++### Removed++  * The `reshape` construct has been removed.  Use the+    `flatten`/`unflatten` functions instead.++  * `concat` and `rotate` no longer support the `@` notation.  Use+    `map` nests instead.++  * Removed `-I`/`--library`.  These never worked with+    `futhark-test`/`futhark-bench` anyway.++### Changed++  * When defining a module type, a module of the same name is no+    longer defined (#538).++  * The `default` keyword is no longer supported.++  * `/futlib/merge_sort` and `/futlib/radix_sort` now define+    functions instead of modules.++### Fixed++  * Better type inference for `rearrange` and `rotate`.++  * `import` path resolution is now much more robust.++## [0.4.1]++### Added++  * Unused-result elimination for reductions; particularly useful when+    computing with dual numbers for automatic differentiation.++  * Record field projection is now possible for variables of (then)+    unknown types.  A function parameter must still have an+    unambiguous (complete) type by the time it finishes checking.++### Fixed++  * Fixed interaction between type ascription and type inference (#529).++  * Fixed duplication when an entry point was also called as a function.++  * Futhark now compiles cleanly with GHC 8.4.1 (this is also the new default).++## [0.4.0]++### Added++   * The constructor for generated PyOpenCL classes now accepts a+     `command_queue` parameter (#480).++   * Transposing small arrays is now much faster when using OpenCL+     backend (#478).++   * Infix operators can now be defined in prefix notation, e.g.:++         let (+) (x: i32) (y: i32) = x - y++     This permits them to have type- and shape parameters.++   * Comparison operators (<=, <, >, >=) are now valid for boolean+     operands.++   * Ordinary functions can be used as infix by enclosing them in+     backticks, as in Haskell.  They are left-associative and have+     lowest priority.++   * Numeric modules now have `largest`/`smallest` values.++   * Numeric modules now have `sum`, `product`, `maximum`, and+     `minimum` functions.++   * Added ``--Werror`` command line option to compilers.++   * Higher-order functions are now supported (#323).++   * Type inference is now supported, although with some limitations+     around records, in-place updates, and `unzip`. (#503)++   * Added a range of higher-order utility functions to the prelude,+     including (among others):++         val (|>) '^a '^b: a ->  (a -> b) -> b++         val (<|) '^a '^b: (a -> b) -> a -> b++         val (|>>) '^a 'b '^c: (a -> b) -> (b -> c) -> a -> c++         val (<<|) '^a 'b '^c: (b -> c) -> (a -> b) a -> c++### Changed++   * `FUTHARK_VERSIONED_CODE` is now `FUTHARK_INCREMENTAL_FLATTENING`.++   * The SOACs `map`, `reduce`, `filter`, `partition`, `scan`,+     `stream_red,` and `stream_map` have been replaced with library+     functions.++   * The futlib/mss and futlib/lss modules have been rewritten to use+     higher-order functions instead of modules.++### Fixed++   * Transpositions in generated OpenCL code no longer crashes on+     large but empty arrays (#483).++   * Booleans can now be compared with relational operators without+     crashing the compiler (#499).++## [0.3.1]++### Added++   * `futhark-bench` now tries to align benchmark results for better+     legibility.++### Fixed++   * `futhark-test`: now handles CRLF linebreaks correctly (#471).++   * A record field can be projected from an array index expression (#473).++   * Futhark will now never automatically pick Apple's CPU device for+     OpenCL, as it is rather broken.  You can still select it+     manually (#475).++   * Fixes to `set_bit` functions in the math module (#476).++## [0.3.0]++### Added++   * A comprehensible error message is now issued when attempting to+     run a Futhark program on an OpenCL that does not support the+     types used by the program.  A common case was trying to use+     double-precision floats on an Intel GPU.++   * Parallelism inside of a branch can now be exploited if the branch+     condition and the size of its results is invariant to all+     enclosing parallel loops.++   * A new OpenCL memory manager can in some cases dramatically+     improve performance for repeated invocations of the same entry+     point.++   * Experimental support for incremental flattening.  Set the+     environment variable `FUTHARK_VERSIONED_CODE` to any value to try+     it out.++   * `futhark-dataset`: Add `-t`/`-type` option.  Useful for+     inspecting data files.++   * Better error message when ranges written with two dots+     (`x..y`).++   * Type errors involving abstract types from modules now use+     qualified names (less "expected 't', got 't'", more "expected+     'foo.t', got 'bar.t'").++   * Shorter compile times for most programs.++   * `futhark-bench`: Add ``--skip-compilation`` flag.++   * `scatter` expressions nested in `map`s are now parallelised.++   * futlib: an `fft` module has been added, thanks to David+     P.H. Jørgensen and Kasper Abildtrup Hansen.++### Removed++   * `futhark-dataset`: Removed `--binary-no-header` and+     `--binary-only-header` options.++   * The `split` language construct has been removed.  There is a+     library function `split` that does approximately the same.++### Changed++  * futlib: the `complex` module now produces a non-abstract `complex`+    type.++  * futlib: the `random` module has been overhauled, with several new+    engines and adaptors changed, and some of the module types+    changed.  In particular, `rng_distribution` now contains a numeric+    module instead of an abstract type.++  * futlib: The `vec2` and `vec3` modules now represent vectors as+    records rather than tuples.++  * futlib: The `linalg` module now has distinct convenience functions+    for multiplying matrices with row and column vectors.++  * Only entry points defined directly in the file given to the+    compiler will be visible.++  * Range literals are now written without brackets: `x...y`.++  * The syntax `(-x)` can no longer be used for a partial application+    of subtraction.++  * `futhark-test` and `futhark-bench` will no longer append `.bin` to+    executables.++  * `futhark-test` and `futhark-bench` now replaces actual/expected+    files from previous runs, rather than increasing the litter.++### Fixed++  * Fusion would sometimes remove safety checks on e.g. `reshape`+    (#436).++  * Variables used as implicit fields in a record construction are now+    properly recognised as being used.++  * futlib: the `num_bits` field for the integer modules in `math` now+    have correct values.++## [0.2.0]++### Added++  * Run-time errors due to failed assertions now include a stack+    trace.++  * Generated OpenCL code now picks more sensible group size and count+    when running on a CPU.++  * `scatter` expressions nested in `map`s may now be parallelised+    ("segmented scatter").++  * Add `num_bits`/`get_bit`/`set_bit` functions to numeric module+    types, including a new `float` module type.++  * Size annotations may now refer to preceding parameters, e.g:++        let f (n: i32) (xs: [n]i32) = ...++  * `futhark-doc`: retain parameter names in generated docs.++  * `futhark-doc`: now takes `-v`/`--verbose` options.++  * `futhark-doc`: now generates valid HTML.++  * `futhark-doc`: now permits files to contain a leading documentation+    comment.++  * `futhark-py`/`futhark-pyopencl`: Better dynamic type checking in+    entry points.++  * Primitive functions (sqrt etc) can now be constant-folded.++  * Futlib: /futlib/vec2 added.++### Removed++  * The built-in `shape` function has been removed.  Use `length` or+    size parameters.++### Changed++  * The `from_i32`/`from_i64` functions of the `numeric` module type+    have been replaced with functions named `i32`/`i64`.  Similarly+    functions have been added for all the other primitive types+    (factored into a new `from_prim` module type).++  * The overloaded type conversion functions (`i32`, `f32`, `bool`,+    etc) have been removed.  Four functions have been introduced for+    the special cases of converting between `f32`/`f64` and `i32`:+    `r32`, `r64`, `t32`, `t64`.++  * Modules and variables now inhabit the same name space.  As a+    consequence, we now use `x.y` to access field `y` of record `x`.++  * Record expression syntax has been simplified.  Record+    concatenation and update is no longer directly supported.+    However, fields can now be implicitly defined: `{x,y}` now creates+    a record with field `x` and `y`, with values taken from the+    variables `x` and `y` in scope.++### Fixed++  * The `!=` operator now works properly on arrays (#426).++  * Allocations were sometimes hoisted incorrectly (#419).++  * `f32.e` is no longer pi.++  * Various other fixes.++## [0.1.0]++  (This is just a list of highlights of what was included in the first+   release.)++  * Code generators: Python and C, both with OpenCL.++  * Higher-order ML-style module system.++  * In-place updates.++  * Tooling: futhark-test, futhark-bench, futhark-dataset, futhark-doc.++  * Beginnings of a basis library, "futlib".
+ README.md view
@@ -0,0 +1,40 @@+<img src="assets/logo.svg" height="50px"/> The Futhark Programming Language+==========++[![Join the chat at https://gitter.im/futhark-lang/Lobby](https://badges.gitter.im/futhark-lang/Lobby.svg)](https://gitter.im/futhark-lang/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)[![CI](https://github.com/diku-dk/futhark/workflows/CI/badge.svg)](https://github.com/diku-dk/futhark/actions)[![DOI](https://zenodo.org/badge/7960131.svg)](https://zenodo.org/badge/latestdoi/7960131)++Futhark is a purely functional data-parallel programming language in+the ML family.  It can be compiled to typically very efficient+parallel code, running on either a CPU or GPU.  The language is+developed at [DIKU](http://diku.dk) at the University of Copenhagen,+originally as part of the [HIPERFIT centre](http://hiperfit.dk).  It+is quite stable and suitable for practical programming.++For more information, see:++* [A collection of code examples](https://futhark-lang.org/examples.html)++* [Installation instructions](http://futhark.readthedocs.io/en/latest/installation.html)++* [The main website](http://futhark-lang.org)++* [Parallel Programming in+  Futhark](https://futhark-book.readthedocs.io/en/latest/), an+  extensive introduction and guide++* [The Futhark User's Guide](http://futhark.readthedocs.io)++* [Documentation for the built-in prelude](https://futhark-lang.org/docs/prelude)++* [Futhark libraries](https://futhark-lang.org/pkgs/)++[![Packaging status](https://repology.org/badge/vertical-allrepos/futhark.svg)](https://repology.org/project/futhark/versions)++Hacking+=======++Issues tagged with [good first+issue](https://github.com/diku-dk/futhark/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)+do not require deep knowledge of the code base.++For contributing code, see [the hacking instructions](HACKING.md).
futhark.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name:           futhark-version:        0.25.8+version:        0.25.9 synopsis:       An optimising compiler for a functional, array-oriented language.  description:    Futhark is a small programming language designed to be compiled to@@ -14,7 +14,7 @@                 .                 For introductionary information about hacking on the                 Futhark compiler, see-                <https://futhark.readthedocs.io/en/latest/hacking.html the hacking guide>.+                <https://github.com/diku-dk/futhark/blob/master/HACKING.md the hacking guide>.                 Regarding the internal design of the compiler, the following modules make                 good starting points:                 .@@ -92,64 +92,18 @@     docs/requirements.txt extra-doc-files:   assets/*.png+  CHANGELOG.md+  README.md  source-repository head   type: git   location: https://github.com/diku-dk/futhark  common common-  ghc-options: -Wall -Wcompat -Wno-incomplete-uni-patterns -Wredundant-constraints -Wincomplete-record-updates -Wmissing-export-lists -Wunused-packages-  default-language: Haskell2010+  ghc-options: -Wall -Wcompat -Wno-incomplete-uni-patterns -Wno-x-partial -Wno-unrecognised-warning-flags  -Wredundant-constraints -Wincomplete-record-updates -Wmissing-export-lists -Wunused-packages+  default-language: GHC2021   default-extensions:     OverloadedStrings-    -- The following extensions correspond to the GHC2021 language,-    -- but we want to remain compatible with GHC 9.0, so we cannot use-    -- it just yet.-    BangPatterns-    BinaryLiterals-    ConstrainedClassMethods-    ConstraintKinds-    DeriveDataTypeable-    DeriveFoldable-    DeriveFunctor-    DeriveGeneric-    DeriveLift-    DeriveTraversable-    DoAndIfThenElse-    EmptyCase-    EmptyDataDecls-    EmptyDataDeriving-    ExistentialQuantification-    ExplicitForAll-    FlexibleContexts-    FlexibleInstances-    ForeignFunctionInterface-    GADTSyntax-    GeneralisedNewtypeDeriving-    HexFloatLiterals-    ImplicitPrelude-    ImportQualifiedPost-    InstanceSigs-    KindSignatures-    MonomorphismRestriction-    MultiParamTypeClasses-    NamedFieldPuns-    NamedWildCards-    NumericUnderscores-    PatternGuards-    PolyKinds-    PostfixOperators-    RankNTypes-    RelaxedPolyRec-    ScopedTypeVariables-    StandaloneDeriving-    StandaloneKindSignatures-    StarIsType-    TraditionalRecordSyntax-    TupleSections-    TypeApplications-    TypeOperators-    TypeSynonymInstances  library   import: common
prelude/array.fut view
@@ -18,47 +18,56 @@ -- | The first element of the array. -- -- **Complexity:** O(1).+#[inline] def head [n] 't (x: [n]t) = x[0]  -- | The last element of the array. -- -- **Complexity:** O(1).+#[inline] def last [n] 't (x: [n]t) = x[n-1]  -- | Everything but the first element of the array. -- -- **Complexity:** O(1).+#[inline] def tail [n] 't (x: [n]t): [n-1]t = x[1:]  -- | Everything but the last element of the array. -- -- **Complexity:** O(1).+#[inline] def init [n] 't (x: [n]t): [n-1]t = x[0:n-1]  -- | Take some number of elements from the head of the array. -- -- **Complexity:** O(1).+#[inline] def take [n] 't (i: i64) (x: [n]t): [i]t = x[0:i]  -- | Remove some number of elements from the head of the array. -- -- **Complexity:** O(1).+#[inline] def drop [n] 't (i: i64) (x: [n]t): [n-i]t = x[i:]  -- | Statically change the size of an array.  Fail at runtime if the -- imposed size does not match the actual size.  Essentially syntactic -- sugar for a size coercion.+#[inline] def sized [m] 't (n: i64) (xs: [m]t) : [n]t = xs :> [n]t  -- | Split an array at a given position. -- -- **Complexity:** O(1).+#[inline] def split [n][m] 't (xs: [n+m]t): ([n]t, [m]t) =   (xs[0:n], xs[n:n+m] :> [m]t)  -- | Return the elements of the array in reverse order. -- -- **Complexity:** O(1).+#[inline] def reverse [n] 't (x: [n]t): [n]t = x[::-1]  -- | Concatenate two arrays.  Warning: never try to perform a reduction@@ -67,9 +76,11 @@ -- **Work:** O(n). -- -- **Span:** O(1).+#[inline] def (++) [n] [m] 't (xs: [n]t) (ys: [m]t): *[n+m]t = intrinsics.concat xs ys  -- | An old-fashioned way of saying `++`.+#[inline] def concat [n] [m] 't (xs: [n]t) (ys: [m]t): *[n+m]t = xs ++ ys  -- | Construct an array of consecutive integers of the given length,@@ -78,6 +89,7 @@ -- **Work:** O(n). -- -- **Span:** O(1).+#[inline] def iota (n: i64): *[n]i64 =   0..1..<n @@ -87,6 +99,7 @@ -- **Work:** O(n). -- -- **Span:** O(1).+#[inline] def indices [n] 't (_: [n]t) : *[n]i64 =   iota n @@ -101,6 +114,7 @@ -- -- Note: In most cases, `rotate` will be fused with subsequent -- operations such as `map`, in which case it is free.+#[inline] def rotate [n] 't (r: i64) (a: [n]t) =   map (\i -> #[unsafe] a[(i+r)%n]) (iota n) @@ -110,6 +124,7 @@ -- **Work:** O(n). -- -- **Span:** O(1).+#[inline] def replicate 't (n: i64) (x: t): *[n]t =   map (const x) (iota n) @@ -118,40 +133,48 @@ -- **Work:** O(n). -- -- **Span:** O(1).+#[inline] def copy 't (a: t): *t =   ([a])[0]  -- | Combines the outer two dimensions of an array. -- -- **Complexity:** O(1).+#[inline] def flatten [n][m] 't (xs: [n][m]t): [n*m]t =   intrinsics.flatten xs  -- | Like `flatten`, but on the outer three dimensions of an array.+#[inline] def flatten_3d [n][m][l] 't (xs: [n][m][l]t): [n*m*l]t =   flatten (flatten xs)  -- | Like `flatten`, but on the outer four dimensions of an array.+#[inline] def flatten_4d [n][m][l][k] 't (xs: [n][m][l][k]t): [n*m*l*k]t =   flatten (flatten_3d xs)  -- | Splits the outer dimension of an array in two. -- -- **Complexity:** O(1).+#[inline] def unflatten 't [n][m] (xs: [n*m]t): [n][m]t =   intrinsics.unflatten n m xs  -- | Like `unflatten`, but produces three dimensions.+#[inline] def unflatten_3d 't [n][m][l] (xs: [n*m*l]t): [n][m][l]t =   unflatten (unflatten xs)  -- | Like `unflatten`, but produces four dimensions.+#[inline] def unflatten_4d 't [n][m][l][k] (xs: [n*m*l*k]t): [n][m][l][k]t =   unflatten (unflatten_3d xs)  -- | Transpose an array. -- -- **Complexity:** O(1).+#[inline] def transpose [n] [m] 't (a: [n][m]t): [m][n]t =   intrinsics.transpose a 
prelude/math.fut view
@@ -87,15 +87,21 @@   -- one of the operands is negative.  May be more efficient.   val %%: t -> t -> t +  -- | Bitwise and.   val &: t -> t -> t+  -- | Bitwise or.   val |: t -> t -> t+  -- | Bitwise xor.   val ^: t -> t -> t    -- | Bitwise negation.   val not: t -> t +  -- | Left shift; inserting zeroes.   val <<: t -> t -> t+  -- | Arithmetic right shift, using sign extension for the leftmost bits.   val >>: t -> t -> t+  -- | Logical right shift, inserting zeroes for the leftmost bits.   val >>>: t -> t -> t    val num_bits: i32@@ -248,6 +254,9 @@   -- | Produces the next representable number from `x` in the   -- direction of `y`.   val nextafter : (x: t) -> (y: t) -> t++  -- | Multiplies floating-point value by 2 raised to an integer power.+  val ldexp : t -> i32 -> t }  -- | Boolean numbers.  When converting from a number to `bool`, 0 is@@ -961,6 +970,7 @@   def round = intrinsics.round64    def nextafter x y = intrinsics.nextafter64 (x,y)+  def ldexp x y = intrinsics.ldexp64 (x,y)    def to_bits (x: f64): u64 = u64m.i64 (intrinsics.to_bits64 x)   def from_bits (x: u64): f64 = intrinsics.from_bits64 (intrinsics.sign_i64 x)@@ -1076,6 +1086,7 @@   def round = intrinsics.round32    def nextafter x y = intrinsics.nextafter32 (x,y)+  def ldexp x y = intrinsics.ldexp32 (x,y)    def to_bits (x: f32): u32 = u32m.i32 (intrinsics.to_bits32 x)   def from_bits (x: u32): f32 = intrinsics.from_bits32 (intrinsics.sign_i32 x)@@ -1195,6 +1206,7 @@   def round = intrinsics.round16    def nextafter x y = intrinsics.nextafter16 (x,y)+  def ldexp x y = intrinsics.ldexp16 (x,y)    def to_bits (x: f16): u16 = u16m.i16 (intrinsics.to_bits16 x)   def from_bits (x: u16): f16 = intrinsics.from_bits16 (intrinsics.sign_i16 x)
rts/c/scalar.h view
@@ -1886,6 +1886,10 @@   return mix(v0, v1, t); } +SCALAR_FUN_ATTR float futrts_ldexp32(float x, int32_t y) {+  return ldexp(x, y);+}+ SCALAR_FUN_ATTR float futrts_mad32(float a, float b, float c) {   return mad(a, b, c); }@@ -2095,6 +2099,10 @@   return v0 + (v1 - v0) * t; } +SCALAR_FUN_ATTR float futrts_ldexp32(float x, int32_t y) {+  return x * pow((double)2.0, (double)y);+}+ SCALAR_FUN_ATTR float futrts_mad32(float a, float b, float c) {   return a * b + c; }@@ -2229,6 +2237,10 @@   return v0 + (v1 - v0) * t; } +SCALAR_FUN_ATTR float futrts_ldexp32(float x, int32_t y) {+  return ldexpf(x, y);+}+ SCALAR_FUN_ATTR float futrts_mad32(float a, float b, float c) {   return a * b + c; }@@ -2640,6 +2652,10 @@   return v0 + (v1 - v0) * t; } +SCALAR_FUN_ATTR float futrts_ldexp64(double x, int32_t y) {+  return x * pow((double)2.0, (double)y);+}+ SCALAR_FUN_ATTR double futrts_mad64(double a, double b, double c) {   return a * b + c; }@@ -2968,6 +2984,10 @@ #else   return v0 + (v1 - v0) * t; #endif+}++SCALAR_FUN_ATTR double futrts_ldexp64(double x, int32_t y) {+  return ldexp(x, y); }  SCALAR_FUN_ATTR double futrts_mad64(double a, double b, double c) {
rts/c/scalar_f16.h view
@@ -170,6 +170,7 @@ SCALAR_FUN_ATTR f16 fpow16(f16 x, f16 y) {   return pow(x, y); }+ #else // Assuming CUDA.  SCALAR_FUN_ATTR f16 fabs16(f16 x) {@@ -329,6 +330,10 @@   return mix(v0, v1, t); } +SCALAR_FUN_ATTR f16 futrts_ldexp16(f16 x, int32_t y) {+  return ldexp(x, y);+}+ SCALAR_FUN_ATTR f16 futrts_mad16(f16 a, f16 b, f16 c) {   return mad(a, b, c); }@@ -486,6 +491,10 @@   return v0 + (v1 - v0) * t; } +SCALAR_FUN_ATTR f16 futrts_ldexp16(f16 x, int32_t y) {+  return futrts_ldexp32((float)x, y);+}+ SCALAR_FUN_ATTR f16 futrts_mad16(f16 a, f16 b, f16 c) {   return a * b + c; }@@ -620,6 +629,10 @@   return v0 + (v1 - v0) * t; } +SCALAR_FUN_ATTR f16 futrts_ldexp16(f16 x, int32_t y) {+  return futrts_ldexp32((float)x, y);+}+ SCALAR_FUN_ATTR f16 futrts_mad16(f16 a, f16 b, f16 c) {   return a * b + c; }@@ -820,6 +833,10 @@  SCALAR_FUN_ATTR f16 futrts_lerp16(f16 v0, f16 v1, f16 t) {   return futrts_lerp32(v0, v1, t);+}++SCALAR_FUN_ATTR f16 futrts_ldexp16(f16 x, int32_t y) {+  return futrts_ldexp32(x, y); }  SCALAR_FUN_ATTR f16 futrts_mad16(f16 a, f16 b, f16 c) {
rts/python/scalar.py view
@@ -990,6 +990,18 @@     return v0 + (v1 - v0) * t  +def futhark_ldexp16(x, y):+    return np.ldexp(x, y)+++def futhark_ldexp32(x, y):+    return np.ldexp(x, y)+++def futhark_ldexp64(x, y):+    return np.ldexp(x, y)++ def futhark_mad16(a, b, c):     return a * b + c 
src/Futhark/AD/Derivatives.hs view
@@ -339,6 +339,21 @@       untyped $ fMax64 0 (fMin64 1 (isF64 t)),       untyped $ isF64 v1 - isF64 v0     ]+pdBuiltin "ldexp16" [x, y] =+  Just+    [ untyped $ 2 ** isF16 x,+      untyped $ log 2 * (2 ** isF16 y) * isF16 x+    ]+pdBuiltin "ldexp32" [x, y] =+  Just+    [ untyped $ 2 ** isF32 x,+      untyped $ log 2 * (2 ** isF32 y) * isF32 x+    ]+pdBuiltin "ldexp64" [x, y] =+  Just+    [ untyped $ 2 ** isF64 x,+      untyped $ log 2 * (2 ** isF64 y) * isF64 x+    ] pdBuiltin "erf16" [z] =   Just [untyped $ (2 / sqrt pi) * exp (negate (isF16 z * isF16 z))] pdBuiltin "erf32" [z] =
src/Futhark/CLI/Dev.hs view
@@ -451,6 +451,7 @@                 "c" -> Right $ SeqMemAction compileCAction                 "multicore" -> Right $ MCMemAction compileMulticoreAction                 "opencl" -> Right $ GPUMemAction compileOpenCLAction+                "hip" -> Right $ GPUMemAction compileHIPAction                 "cuda" -> Right $ GPUMemAction compileCUDAAction                 "wasm" -> Right $ SeqMemAction compileCtoWASMAction                 "wasm-multicore" -> Right $ MCMemAction compileMulticoreToWASMAction@@ -461,7 +462,7 @@                Right $ \opts -> opts {futharkAction = action}           )-          "c|multicore|opencl|cuda|python|pyopencl"+          "c|multicore|opencl|cuda|hip|python|pyopencl"       )       "Run this compiler backend on pipeline result.",     Option
src/Futhark/CLI/Literate.hs view
@@ -10,7 +10,7 @@ import Data.ByteString qualified as BS import Data.ByteString.Lazy qualified as LBS import Data.Char-import Data.Functor+import Data.Functor (($>)) import Data.Int (Int64) import Data.List (foldl', transpose) import Data.Map qualified as M
src/Futhark/CLI/REPL.hs view
@@ -227,7 +227,7 @@         Right (Right e) -> do           valOrErr <- onExp e           case valOrErr of-            Left err -> liftIO $ putDoc err+            Left err -> liftIO $ putDocLn err             Right val -> liftIO $ putDocLn $ I.prettyValue val   modify $ \s -> s {futharkiCount = futharkiCount s + 1}   where
src/Futhark/CodeGen/ImpGen/GPU/Base.hs view
@@ -290,9 +290,10 @@    let op_to_x in_block_thread_active         | Nothing <- seg_flag =-            sWhen in_block_thread_active $-              compileBody' x_params $-                lambdaBody scan_lam+            localOps threadOperations+              . sWhen in_block_thread_active+              $ compileBody' x_params+              $ lambdaBody scan_lam         | Just flag_true <- seg_flag = do             inactive <-               dPrimVE "inactive" $ flag_true (ltid32 - tvExp skip_threads) ltid32@@ -302,9 +303,11 @@             -- The convoluted control flow is to ensure all threads             -- hit this barrier (if applicable).             when array_scan barrier-            sWhen in_block_thread_active . sUnless inactive $-              compileBody' x_params $-                lambdaBody scan_lam+            localOps threadOperations+              . sWhen in_block_thread_active+              . sUnless inactive+              $ compileBody' x_params+              $ lambdaBody scan_lam        maybeBarrier =         sWhen@@ -498,10 +501,11 @@           when (primType $ paramType p) $             copyDWIM arr [DimFix ltid] (Var $ paramName p) [] -  sComment "carry-in for every block except the first" $ do-    sComment "read operands" read_carry_in-    sComment "perform operation" op_to_x-    sComment "write final result" $ sUnless no_carry_in write_final_result+  sComment "carry-in for every block except the first" $+    localOps threadOperations $ do+      sComment "read operands" read_carry_in+      sComment "perform operation" op_to_x+      sComment "write final result" $ sUnless no_carry_in write_final_result    barrier 
src/Futhark/CodeGen/ImpGen/GPU/SegScan.hs view
@@ -14,8 +14,8 @@  -- The single-pass scan does not support multiple operators, so jam -- them together here.-combineScans :: [SegBinOp GPUMem] -> SegBinOp GPUMem-combineScans ops =+combineScanOps :: [SegBinOp GPUMem] -> SegBinOp GPUMem+combineScanOps ops =   SegBinOp     { segBinOpComm = mconcat (map segBinOpComm ops),       segBinOpLambda = lam',@@ -48,13 +48,11 @@         { walkOnBody = const $ guard . not . bodyHas f         } -canBeSinglePass :: [SegBinOp GPUMem] -> KernelBody GPUMem -> Maybe (SegBinOp GPUMem)-canBeSinglePass ops kbody-  | all ok ops,-    not $ bodyHas freshArray (Body () (kernelBodyStms kbody) []) =-      Just $ combineScans ops-  | otherwise =-      Nothing+canBeSinglePass :: [SegBinOp GPUMem] -> Maybe (SegBinOp GPUMem)+canBeSinglePass scan_ops =+  if all ok scan_ops+    then Just $ combineScanOps scan_ops+    else Nothing   where     ok op =       segBinOpShape op == mempty@@ -62,16 +60,6 @@         && not (bodyHas isAssert (lambdaBody (segBinOpLambda op)))     isAssert (BasicOp Assert {}) = True     isAssert _ = False-    -- XXX: Currently single pass scans cannot handle construction of-    -- arrays in the kernel body (#2013), because of insufficient-    -- memory expansion.  This can in principle be fixed.-    freshArray (BasicOp Manifest {}) = True-    freshArray (BasicOp Iota {}) = True-    freshArray (BasicOp Replicate {}) = True-    freshArray (BasicOp Scratch {}) = True-    freshArray (BasicOp Concat {}) = True-    freshArray (BasicOp ArrayLit {}) = True-    freshArray _ = False  -- | Compile 'SegScan' instance to host-level code with calls to -- various kernels.@@ -82,17 +70,19 @@   [SegBinOp GPUMem] ->   KernelBody GPUMem ->   CallKernelGen ()-compileSegScan pat lvl space scans kbody = sWhen (0 .<. n) $ do-  emit $ Imp.DebugPrint "\n# SegScan" Nothing-  target <- hostTarget <$> askEnv-  case target of-    CUDA-      | Just scan' <- canBeSinglePass scans kbody ->-          SinglePass.compileSegScan pat lvl space scan' kbody-    HIP-      | Just scan' <- canBeSinglePass scans kbody ->-          SinglePass.compileSegScan pat lvl space scan' kbody-    _ -> TwoPass.compileSegScan pat lvl space scans kbody-  emit $ Imp.DebugPrint "" Nothing+compileSegScan pat lvl space scan_ops map_kbody =+  sWhen (0 .<. n) $ do+    emit $ Imp.DebugPrint "\n# SegScan" Nothing+    target <- hostTarget <$> askEnv++    case (targetSupportsSinglePass target, canBeSinglePass scan_ops) of+      (True, Just scan_ops') ->+        SinglePass.compileSegScan pat lvl space scan_ops' map_kbody+      _ ->+        TwoPass.compileSegScan pat lvl space scan_ops map_kbody+    emit $ Imp.DebugPrint "" Nothing   where     n = product $ map pe64 $ segSpaceDims space+    targetSupportsSinglePass CUDA = True+    targetSupportsSinglePass HIP = True+    targetSupportsSinglePass _ = False
src/Futhark/CodeGen/ImpGen/GPU/SegScan/SinglePass.hs view
@@ -6,7 +6,7 @@ module Futhark.CodeGen.ImpGen.GPU.SegScan.SinglePass (compileSegScan) where  import Control.Monad-import Data.List (zip4)+import Data.List (zip4, zip7) import Data.Maybe import Futhark.CodeGen.ImpCode.GPU qualified as Imp import Futhark.CodeGen.ImpGen@@ -32,9 +32,9 @@   SubExp ->   [PrimType] ->   InKernelGen (VName, [VName], [VName], VName, [VName])-createLocalArrays (Count groupSize) m types = do+createLocalArrays (Count groupSize) chunk types = do   let groupSizeE = pe64 groupSize-      workSize = pe64 m * groupSizeE+      workSize = pe64 chunk * groupSizeE       prefixArraysSize =         foldl (\acc tySize -> alignTo acc tySize + tySize * groupSizeE) 0 $           map primByteSize types@@ -67,7 +67,7 @@       warpSize       $ map primByteSize types -  sComment "Allocate reused shared memeory" $ pure ()+  sComment "Allocate reusable shared memory" $ pure ()    localMem <- sAlloc "local_mem" size (Space "local")   transposeArrayLength <- dPrimV "trans_arr_len" workSize@@ -105,6 +105,11 @@    pure (sharedId, transposedArrays, prefixArrays, warpscan, warpExchanges) +statusX, statusA, statusP :: (Num a) => a+statusX = 0+statusA = 1+statusP = 2+ inBlockScanLookback ::   KernelConstants ->   Imp.TExp Int64 ->@@ -118,8 +123,8 @@   let flg_param_x = Param mempty (tvVar flg_x) (MemPrim p_int8)       flg_param_y = Param mempty (tvVar flg_y) (MemPrim p_int8)       flg_y_exp = tvExp flg_y-      statusP = (2 :: Imp.TExp Int8)-      statusX = (0 :: Imp.TExp Int8)+      statusP_e = statusP :: Imp.TExp Int8+      statusX_e = statusX :: Imp.TExp Int8    dLParams (lambdaParams scan_lam) @@ -149,7 +154,7 @@    let op_to_x = do         sIf-          (flg_y_exp .==. statusP .||. flg_y_exp .==. statusX)+          (flg_y_exp .==. statusP_e .||. flg_y_exp .==. statusX_e)           ( do               y_to_x_flg               y_to_x@@ -194,18 +199,18 @@      readInitial p arr       | primType $ paramType p =-          copyDWIM (paramName p) [] (Var arr) [DimFix ltid]+          copyDWIMFix (paramName p) [] (Var arr) [ltid]       | otherwise =-          copyDWIM (paramName p) [] (Var arr) [DimFix gtid]+          copyDWIMFix (paramName p) [] (Var arr) [gtid]     readParam behind p arr       | primType $ paramType p =-          copyDWIM (paramName p) [] (Var arr) [DimFix $ ltid - behind]+          copyDWIMFix (paramName p) [] (Var arr) [ltid - behind]       | otherwise =-          copyDWIM (paramName p) [] (Var arr) [DimFix $ gtid - behind + arrs_full_size]+          copyDWIMFix (paramName p) [] (Var arr) [gtid - behind + arrs_full_size]      writeResult x y arr       | primType $ paramType x = do-          copyDWIM arr [DimFix ltid] (Var $ paramName x) []+          copyDWIMFix arr [ltid] (Var $ paramName x) []           copyDWIM (paramName y) [] (Var $ paramName x) []       | otherwise =           copyDWIM (paramName y) [] (Var $ paramName x) []@@ -219,431 +224,453 @@   SegBinOp GPUMem ->   KernelBody GPUMem ->   CallKernelGen ()-compileSegScan pat lvl space scanOp kbody = do+compileSegScan pat lvl space scan_op map_kbody = do   attrs <- lvlKernelAttrs lvl   let Pat all_pes = pat-      scanOpNe = segBinOpNeutral scanOp-      tys = map (\(Prim pt) -> pt) $ lambdaReturnType $ segBinOpLambda scanOp++      scanop_nes = segBinOpNeutral scan_op+       n = product $ map pe64 $ segSpaceDims space-      sumT :: Integer-      maxT :: Integer-      sumT = foldl (\bytes typ -> bytes + primByteSize typ) 0 tys-      primByteSize' = max 4 . primByteSize-      sumT' = foldl (\bytes typ -> bytes + primByteSize' typ) 0 tys `div` 4-      maxT = maximum (map primByteSize tys)-      m :: (Num a) => a-      m = fromIntegral $ max 1 $ min mem_constraint reg_constraint++      tys = map (\(Prim pt) -> pt) $ lambdaReturnType $ segBinOpLambda scan_op+      tys_sizes = map primByteSize tys++      sumT, maxT :: Integer+      sumT = sum tys_sizes+      sumT' = sum (map (max 4 . primByteSize) tys) `div` 4+      maxT = maximum tys_sizes+       -- TODO: Make these constants dynamic by querying device       k_reg = 64       k_mem = 95+       mem_constraint = max k_mem sumT `div` maxT       reg_constraint = (k_reg - 1 - sumT') `div` (2 * sumT') -      group_size = kAttrGroupSize attrs-      group_size' = pe64 $ unCount group_size+      chunk :: (Num a) => a+      chunk = fromIntegral $ max 1 $ min mem_constraint reg_constraint -  num_groups <--    Count . tvSize <$> dPrimV "num_groups" (n `divUp` (group_size' * m))-  let num_groups' = pe64 (unCount num_groups)+      group_size_e = pe64 $ unCount $ kAttrGroupSize attrs+      num_physgroups_e = pe64 $ unCount $ kAttrNumGroups attrs -  num_threads <--    dPrimVE "num_threads" $ num_groups' * group_size'+  num_virtgroups <-+    tvSize <$> dPrimV "num_virtgroups" (n `divUp` (group_size_e * chunk))+  let num_virtgroups_e = pe64 num_virtgroups +  num_virt_threads <-+    dPrimVE "num_virt_threads" $ num_virtgroups_e * group_size_e+   let (gtids, dims) = unzip $ unSegSpace space       dims' = map pe64 dims       segmented = length dims' > 1-      not_segmented_e = if segmented then false else true+      not_segmented_e = fromBool $ not segmented       segment_size = last dims' -      statusX, statusA, statusP :: (Num a) => a-      statusX = 0-      statusA = 1-      statusP = 2+  let debug_ s v = emit $ Imp.DebugPrint s $ Just $ untyped (v :: Imp.TExp Int32)+  debug_ "Sequential elements per thread (chunk) " chunk+  debug_ "Memory constraint" $ fromIntegral mem_constraint+  debug_ "Register constraint" $ fromIntegral reg_constraint+  debug_ "sumT'" $ fromIntegral sumT' -  emit $ Imp.DebugPrint "Sequential elements per thread (m) " $ Just $ untyped (m :: Imp.TExp Int32)-  emit $ Imp.DebugPrint "Memory constraint" $ Just $ untyped (fromIntegral mem_constraint :: Imp.TExp Int32)-  emit $ Imp.DebugPrint "Register constraint" $ Just $ untyped (fromIntegral reg_constraint :: Imp.TExp Int32)-  emit $ Imp.DebugPrint "sumT'" $ Just $ untyped (fromIntegral sumT' :: Imp.TExp Int32)+  statusFlags <- sAllocArray "status_flags" int8 (Shape [num_virtgroups]) (Space "device")+  sReplicate statusFlags $ intConst Int8 statusX -  globalId <- genZeroes "id_counter" 1-  statusFlags <- sAllocArray "status_flags" int8 (Shape [unCount num_groups]) (Space "device")   (aggregateArrays, incprefixArrays) <-     fmap unzip $       forM tys $ \ty ->         (,)-          <$> sAllocArray "aggregates" ty (Shape [unCount num_groups]) (Space "device")-          <*> sAllocArray "incprefixes" ty (Shape [unCount num_groups]) (Space "device")+          <$> sAllocArray "aggregates" ty (Shape [num_virtgroups]) (Space "device")+          <*> sAllocArray "incprefixes" ty (Shape [num_virtgroups]) (Space "device") -  sReplicate statusFlags $ intConst Int8 statusX+  global_id <- genZeroes "global_dynid" 1 -  sKernelThread "segscan" (segFlat space) (defKernelAttrs num_groups group_size) $ do+  sKernelThread "segscan" (segFlat space) attrs $ do     constants <- kernelConstants <$> askEnv      (sharedId, transposedArrays, prefixArrays, warpscan, exchanges) <--      createLocalArrays (kAttrGroupSize attrs) (intConst Int64 m) tys+      createLocalArrays (kAttrGroupSize attrs) (intConst Int64 chunk) tys -    dynamicId <- dPrim "dynamic_id" int32-    sWhen (kernelLocalThreadId constants .==. 0) $ do-      (globalIdMem, _, globalIdOff) <- fullyIndexArray globalId [0]-      sOp $-        Imp.Atomic DefaultSpace $-          Imp.AtomicAdd-            Int32-            (tvVar dynamicId)-            globalIdMem-            (Count $ unCount globalIdOff)-            (untyped (1 :: Imp.TExp Int32))-      copyDWIMFix sharedId [0] (tvSize dynamicId) []+    -- We wrap the entire kernel body in a virtualisation loop to handle the+    -- case where we do not have enough workgroups to cover the iteration space.+    -- Dynamic group indexing has no implication on this, since each group+    -- simply fetches a new dynamic ID upon entry into the virtualisation loop.+    --+    -- We could use virtualiseGroups, but this introduces a barrier which is+    -- redundant in this case, and also we don't need to base virtual group IDs+    -- on the loop variable, but rather on the dynamic IDs.+    physgroup_id <- dPrim "physgroup_id" int32+    sOp $ Imp.GetGroupId (tvVar physgroup_id) 0+    iters <-+      dPrimVE "virtloop_bound" $+        (num_virtgroups_e - tvExp physgroup_id)+          `divUp` num_physgroups_e -    let localBarrier = Imp.Barrier Imp.FenceLocal-        localFence = Imp.MemFence Imp.FenceLocal-        globalFence = Imp.MemFence Imp.FenceGlobal+    sFor "virtloop_i" iters $ const $ do+      dyn_id <- dPrim "dynamic_id" int32+      sComment "First thread in block fetches this block's dynamic_id" $ do+        sWhen (kernelLocalThreadId constants .==. 0) $ do+          (globalIdMem, _, globalIdOff) <- fullyIndexArray global_id [0]+          sOp $+            Imp.Atomic DefaultSpace $+              Imp.AtomicAdd+                Int32+                (tvVar dyn_id)+                globalIdMem+                (Count $ unCount globalIdOff)+                (untyped (1 :: Imp.TExp Int32))+          sComment "Set dynamic id for this block" $ do+            copyDWIMFix sharedId [0] (tvSize dyn_id) [] -    sOp localBarrier-    copyDWIMFix (tvVar dynamicId) [] (Var sharedId) [0]-    sOp localBarrier+          sComment "First thread in last (virtual) block resets global dynamic_id" $ do+            sWhen (tvExp dyn_id .==. num_virtgroups_e - 1) $+              copyDWIMFix global_id [0] (intConst Int32 0) [] -    blockOff <--      dPrimV "blockOff" $-        sExt64 (tvExp dynamicId) * m * kernelGroupSize constants-    sgmIdx <- dPrimVE "sgm_idx" $ tvExp blockOff `mod` segment_size-    boundary <--      dPrimVE "boundary" $-        sExt32 $-          sMin64 (m * group_size') (segment_size - sgmIdx)-    segsize_compact <--      dPrimVE "segsize_compact" $-        sExt32 $-          sMin64 (m * group_size') segment_size-    privateArrays <--      forM tys $ \ty ->-        sAllocArray-          "private"-          ty-          (Shape [intConst Int64 m])-          (ScalarSpace [intConst Int64 m] ty)+      let local_barrier = Imp.Barrier Imp.FenceLocal+          local_fence = Imp.MemFence Imp.FenceLocal+          global_fence = Imp.MemFence Imp.FenceGlobal -    sComment "Load and map" $-      sFor "i" m $ \i -> do-        -- The map's input index-        phys_tid <--          dPrimVE "phys_tid" $-            tvExp blockOff-              + sExt64 (kernelLocalThreadId constants)-              + i * kernelGroupSize constants-        dIndexSpace (zip gtids dims') phys_tid-        -- Perform the map-        let in_bounds =-              compileStms mempty (kernelBodyStms kbody) $ do-                let (all_scan_res, map_res) = splitAt (segBinOpResults [scanOp]) $ kernelBodyResult kbody+      sOp local_barrier+      copyDWIMFix (tvVar dyn_id) [] (Var sharedId) [0]+      sOp local_barrier -                -- Write map results to their global memory destinations-                forM_ (zip (takeLast (length map_res) all_pes) map_res) $ \(dest, src) ->-                  copyDWIMFix (patElemName dest) (map Imp.le64 gtids) (kernelResultSubExp src) []+      blockOff <-+        dPrimV "blockOff" $+          sExt64 (tvExp dyn_id) * chunk * group_size_e -- kernelGroupSize constants+      sgmIdx <- dPrimVE "sgm_idx" $ tvExp blockOff `mod` segment_size+      boundary <-+        dPrimVE "boundary" $+          sExt32 $+            sMin64 (chunk * group_size_e) (segment_size - sgmIdx)+      segsize_compact <-+        dPrimVE "segsize_compact" $+          sExt32 $+            sMin64 (chunk * group_size_e) segment_size+      privateArrays <-+        forM tys $ \ty ->+          sAllocArray+            "private"+            ty+            (Shape [intConst Int64 chunk])+            (ScalarSpace [intConst Int64 chunk] ty) -                -- Write to-scan results to private memory.-                forM_ (zip privateArrays $ map kernelResultSubExp all_scan_res) $ \(dest, src) ->-                  copyDWIMFix dest [i] src []+      sComment "Load and map" $+        sFor "i" chunk $ \i -> do+          -- The map's input index+          virt_tid <-+            dPrimVE "virt_tid" $+              tvExp blockOff+                + sExt64 (kernelLocalThreadId constants)+                + i * kernelGroupSize constants+          dIndexSpace (zip gtids dims') virt_tid+          -- Perform the map+          let in_bounds =+                compileStms mempty (kernelBodyStms map_kbody) $ do+                  let (all_scan_res, map_res) =+                        splitAt (segBinOpResults [scan_op]) $ kernelBodyResult map_kbody -            out_of_bounds =-              forM_ (zip privateArrays scanOpNe) $ \(dest, ne) ->-                copyDWIMFix dest [i] ne []+                  -- Write map results to their global memory destinations+                  forM_ (zip (takeLast (length map_res) all_pes) map_res) $ \(dest, src) ->+                    copyDWIMFix (patElemName dest) (map Imp.le64 gtids) (kernelResultSubExp src) [] -        sIf (phys_tid .<. n) in_bounds out_of_bounds+                  -- Write to-scan results to private memory.+                  forM_ (zip privateArrays $ map kernelResultSubExp all_scan_res) $ \(dest, src) ->+                    copyDWIMFix dest [i] src [] -    sOp $ Imp.ErrorSync Imp.FenceLocal-    sComment "Transpose scan inputs" $ do-      forM_ (zip transposedArrays privateArrays) $ \(trans, priv) -> do-        sFor "i" m $ \i -> do-          sharedIdx <--            dPrimVE "sharedIdx" $-              sExt64 (kernelLocalThreadId constants)-                + i * kernelGroupSize constants-          copyDWIMFix trans [sharedIdx] (Var priv) [i]-        sOp localBarrier-        sFor "i" m $ \i -> do-          sharedIdx <- dPrimV "sharedIdx" $ kernelLocalThreadId constants * m + i-          copyDWIMFix priv [sExt64 i] (Var trans) [sExt64 $ tvExp sharedIdx]-        sOp localBarrier+              out_of_bounds =+                forM_ (zip privateArrays scanop_nes) $ \(dest, ne) ->+                  copyDWIMFix dest [i] ne [] -    sComment "Per thread scan" $ do-      -- We don't need to touch the first element, so only m-1-      -- iterations here.-      globalIdx <--        dPrimVE "gidx" $-          (kernelLocalThreadId constants * m) + 1-      sFor "i" (m - 1) $ \i -> do-        let xs = map paramName $ xParams scanOp-            ys = map paramName $ yParams scanOp-        -- determine if start of segment-        new_sgm <--          if segmented-            then dPrimVE "new_sgm" $ (globalIdx + sExt32 i - boundary) `mod` segsize_compact .==. 0-            else pure false-        -- skip scan of first element in segment-        sUnless new_sgm $ do-          forM_ (zip privateArrays $ zip3 xs ys tys) $ \(src, (x, y, ty)) -> do-            dPrim_ x ty-            dPrim_ y ty-            copyDWIMFix x [] (Var src) [i]-            copyDWIMFix y [] (Var src) [i + 1]+          sIf (virt_tid .<. n) in_bounds out_of_bounds -          compileStms mempty (bodyStms $ lambdaBody $ segBinOpLambda scanOp) $-            forM_ (zip privateArrays $ map resSubExp $ bodyResult $ lambdaBody $ segBinOpLambda scanOp) $ \(dest, res) ->-              copyDWIMFix dest [i + 1] res []+      sOp $ Imp.ErrorSync Imp.FenceLocal+      sComment "Transpose scan inputs" $ do+        forM_ (zip transposedArrays privateArrays) $ \(trans, priv) -> do+          sFor "i" chunk $ \i -> do+            sharedIdx <-+              dPrimVE "sharedIdx" $+                sExt64 (kernelLocalThreadId constants)+                  + i * kernelGroupSize constants+            copyDWIMFix trans [sharedIdx] (Var priv) [i]+          sOp local_barrier+          sFor "i" chunk $ \i -> do+            sharedIdx <- dPrimV "sharedIdx" $ kernelLocalThreadId constants * chunk + i+            copyDWIMFix priv [sExt64 i] (Var trans) [sExt64 $ tvExp sharedIdx]+          sOp local_barrier -    sComment "Publish results in shared memory" $ do-      forM_ (zip prefixArrays privateArrays) $ \(dest, src) ->-        copyDWIMFix dest [sExt64 $ kernelLocalThreadId constants] (Var src) [m - 1]-      sOp localBarrier+      sComment "Per thread scan" $ do+        -- We don't need to touch the first element, so only m-1+        -- iterations here.+        globalIdx <-+          dPrimVE "gidx" $+            (kernelLocalThreadId constants * chunk) + 1+        sFor "i" (chunk - 1) $ \i -> do+          let xs = map paramName $ xParams scan_op+              ys = map paramName $ yParams scan_op+          -- determine if start of segment+          new_sgm <-+            if segmented+              then dPrimVE "new_sgm" $ (globalIdx + sExt32 i - boundary) `mod` segsize_compact .==. 0+              else pure false+          -- skip scan of first element in segment+          sUnless new_sgm $ do+            forM_ (zip4 privateArrays xs ys tys) $ \(src, x, y, ty) -> do+              dPrim_ x ty+              dPrim_ y ty+              copyDWIMFix x [] (Var src) [i]+              copyDWIMFix y [] (Var src) [i + 1] -    let crossesSegment = do-          guard segmented-          Just $ \from to ->-            let from' = (from + 1) * m - 1-                to' = (to + 1) * m - 1-             in (to' - from') .>. (to' + segsize_compact - boundary) `mod` segsize_compact+            compileStms mempty (bodyStms $ lambdaBody $ segBinOpLambda scan_op) $+              forM_ (zip privateArrays $ map resSubExp $ bodyResult $ lambdaBody $ segBinOpLambda scan_op) $ \(dest, res) ->+                copyDWIMFix dest [i + 1] res [] -    scanOp' <- renameLambda $ segBinOpLambda scanOp+      sComment "Publish results in shared memory" $ do+        forM_ (zip prefixArrays privateArrays) $ \(dest, src) ->+          copyDWIMFix dest [sExt64 $ kernelLocalThreadId constants] (Var src) [chunk - 1]+        sOp local_barrier -    accs <- mapM (dPrim "acc") tys-    sComment "Scan results (with warp scan)" $ do-      groupScan-        crossesSegment-        num_threads-        (kernelGroupSize constants)-        scanOp'-        prefixArrays+      let crossesSegment = do+            guard segmented+            Just $ \from to ->+              let from' = (from + 1) * chunk - 1+                  to' = (to + 1) * chunk - 1+               in (to' - from') .>. (to' + segsize_compact - boundary) `mod` segsize_compact -      sOp $ Imp.ErrorSync Imp.FenceLocal+      scan_op1 <- renameLambda $ segBinOpLambda scan_op -      let firstThread acc prefixes =-            copyDWIMFix (tvVar acc) [] (Var prefixes) [sExt64 (kernelGroupSize constants) - 1]-          notFirstThread acc prefixes =-            copyDWIMFix (tvVar acc) [] (Var prefixes) [sExt64 (kernelLocalThreadId constants) - 1]-      sIf-        (kernelLocalThreadId constants .==. 0)-        (zipWithM_ firstThread accs prefixArrays)-        (zipWithM_ notFirstThread accs prefixArrays)+      accs <- mapM (dPrim "acc") tys+      sComment "Scan results (with warp scan)" $ do+        groupScan+          crossesSegment+          num_virt_threads+          (kernelGroupSize constants)+          scan_op1+          prefixArrays -      sOp localBarrier+        sOp $ Imp.ErrorSync Imp.FenceLocal -    prefixes <- forM (zip scanOpNe tys) $ \(ne, ty) ->-      dPrimV "prefix" $ TPrimExp $ toExp' ty ne-    blockNewSgm <- dPrimVE "block_new_sgm" $ sgmIdx .==. 0-    sComment "Perform lookback" $ do-      sWhen (blockNewSgm .&&. kernelLocalThreadId constants .==. 0) $ do-        everythingVolatile $-          forM_ (zip accs incprefixArrays) $ \(acc, incprefixArray) ->-            copyDWIMFix incprefixArray [tvExp dynamicId] (tvSize acc) []-        sOp globalFence-        everythingVolatile $-          copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []-        forM_ (zip scanOpNe accs) $ \(ne, acc) ->-          copyDWIMFix (tvVar acc) [] ne []-      -- end sWhen+        let firstThread acc prefixes =+              copyDWIMFix (tvVar acc) [] (Var prefixes) [sExt64 (kernelGroupSize constants) - 1]+            notFirstThread acc prefixes =+              copyDWIMFix (tvVar acc) [] (Var prefixes) [sExt64 (kernelLocalThreadId constants) - 1]+        sIf+          (kernelLocalThreadId constants .==. 0)+          (zipWithM_ firstThread accs prefixArrays)+          (zipWithM_ notFirstThread accs prefixArrays) -      let warpSize = kernelWaveSize constants-      sWhen (bNot blockNewSgm .&&. kernelLocalThreadId constants .<. warpSize) $ do-        sWhen (kernelLocalThreadId constants .==. 0) $ do+        sOp local_barrier++      prefixes <- forM (zip scanop_nes tys) $ \(ne, ty) ->+        dPrimV "prefix" $ TPrimExp $ toExp' ty ne+      blockNewSgm <- dPrimVE "block_new_sgm" $ sgmIdx .==. 0+      sComment "Perform lookback" $ do+        sWhen (blockNewSgm .&&. kernelLocalThreadId constants .==. 0) $ do+          everythingVolatile $+            forM_ (zip accs incprefixArrays) $ \(acc, incprefixArray) ->+              copyDWIMFix incprefixArray [tvExp dyn_id] (tvSize acc) []+          sOp global_fence+          everythingVolatile $+            copyDWIMFix statusFlags [tvExp dyn_id] (intConst Int8 statusP) []+          forM_ (zip scanop_nes accs) $ \(ne, acc) ->+            copyDWIMFix (tvVar acc) [] ne []+        -- end sWhen++        let warpSize = kernelWaveSize constants+        sWhen (bNot blockNewSgm .&&. kernelLocalThreadId constants .<. warpSize) $ do+          sWhen (kernelLocalThreadId constants .==. 0) $ do+            sIf+              (not_segmented_e .||. boundary .==. sExt32 (group_size_e * chunk))+              ( do+                  everythingVolatile $+                    forM_ (zip aggregateArrays accs) $ \(aggregateArray, acc) ->+                      copyDWIMFix aggregateArray [tvExp dyn_id] (tvSize acc) []+                  sOp global_fence+                  everythingVolatile $+                    copyDWIMFix statusFlags [tvExp dyn_id] (intConst Int8 statusA) []+              )+              ( do+                  everythingVolatile $+                    forM_ (zip incprefixArrays accs) $ \(incprefixArray, acc) ->+                      copyDWIMFix incprefixArray [tvExp dyn_id] (tvSize acc) []+                  sOp global_fence+                  everythingVolatile $+                    copyDWIMFix statusFlags [tvExp dyn_id] (intConst Int8 statusP) []+              )+            everythingVolatile $+              copyDWIMFix warpscan [0] (Var statusFlags) [tvExp dyn_id - 1]+          -- sWhen+          sOp local_fence++          status <- dPrim "status" int8 :: InKernelGen (TV Int8)+          copyDWIMFix (tvVar status) [] (Var warpscan) [0]+           sIf-            (not_segmented_e .||. boundary .==. sExt32 (group_size' * m))-            ( do-                everythingVolatile $-                  forM_ (zip aggregateArrays accs) $ \(aggregateArray, acc) ->-                    copyDWIMFix aggregateArray [tvExp dynamicId] (tvSize acc) []-                sOp globalFence+            (tvExp status .==. statusP)+            ( sWhen (kernelLocalThreadId constants .==. 0) $                 everythingVolatile $-                  copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusA) []+                  forM_ (zip prefixes incprefixArrays) $ \(prefix, incprefixArray) ->+                    copyDWIMFix (tvVar prefix) [] (Var incprefixArray) [tvExp dyn_id - 1]             )             ( do-                everythingVolatile $-                  forM_ (zip incprefixArrays accs) $ \(incprefixArray, acc) ->-                    copyDWIMFix incprefixArray [tvExp dynamicId] (tvSize acc) []-                sOp globalFence-                everythingVolatile $-                  copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []-            )-          everythingVolatile $-            copyDWIMFix warpscan [0] (Var statusFlags) [tvExp dynamicId - 1]-        -- sWhen-        sOp localFence+                readOffset <-+                  dPrimV "readOffset" $+                    sExt32 $+                      tvExp dyn_id - sExt64 (kernelWaveSize constants)+                let loopStop = warpSize * (-1)+                    sameSegment readIdx+                      | segmented =+                          let startIdx = sExt64 (tvExp readIdx + 1) * kernelGroupSize constants * chunk - 1+                           in tvExp blockOff - startIdx .<=. sgmIdx+                      | otherwise = true+                sWhile (tvExp readOffset .>. loopStop) $ do+                  readI <- dPrimV "read_i" $ tvExp readOffset + kernelLocalThreadId constants+                  aggrs <- forM (zip scanop_nes tys) $ \(ne, ty) ->+                    dPrimV "aggr" $ TPrimExp $ toExp' ty ne+                  flag <- dPrimV "flag" (statusX :: Imp.TExp Int8)+                  everythingVolatile . sWhen (tvExp readI .>=. 0) $ do+                    sIf+                      (sameSegment readI)+                      ( do+                          copyDWIMFix (tvVar flag) [] (Var statusFlags) [sExt64 $ tvExp readI]+                          sIf+                            (tvExp flag .==. statusP)+                            ( forM_ (zip incprefixArrays aggrs) $ \(incprefix, aggr) ->+                                copyDWIMFix (tvVar aggr) [] (Var incprefix) [sExt64 $ tvExp readI]+                            )+                            ( sWhen (tvExp flag .==. statusA) $ do+                                forM_ (zip aggrs aggregateArrays) $ \(aggr, aggregate) ->+                                  copyDWIMFix (tvVar aggr) [] (Var aggregate) [sExt64 $ tvExp readI]+                            )+                      )+                      (copyDWIMFix (tvVar flag) [] (intConst Int8 statusP) [])+                  -- end sIf+                  -- end sWhen -        status <- dPrim "status" int8 :: InKernelGen (TV Int8)-        copyDWIMFix (tvVar status) [] (Var warpscan) [0]+                  forM_ (zip exchanges aggrs) $ \(exchange, aggr) ->+                    copyDWIMFix exchange [sExt64 $ kernelLocalThreadId constants] (tvSize aggr) []+                  copyDWIMFix warpscan [sExt64 $ kernelLocalThreadId constants] (tvSize flag) [] -        sIf-          (tvExp status .==. statusP)-          ( sWhen (kernelLocalThreadId constants .==. 0) $-              everythingVolatile $-                forM_ (zip prefixes incprefixArrays) $ \(prefix, incprefixArray) ->-                  copyDWIMFix (tvVar prefix) [] (Var incprefixArray) [tvExp dynamicId - 1]-          )-          ( do-              readOffset <--                dPrimV "readOffset" $-                  sExt32 $-                    tvExp dynamicId - sExt64 (kernelWaveSize constants)-              let loopStop = warpSize * (-1)-                  sameSegment readIdx-                    | segmented =-                        let startIdx = sExt64 (tvExp readIdx + 1) * kernelGroupSize constants * m - 1-                         in tvExp blockOff - startIdx .<=. sgmIdx-                    | otherwise = true-              sWhile (tvExp readOffset .>. loopStop) $ do-                readI <- dPrimV "read_i" $ tvExp readOffset + kernelLocalThreadId constants-                aggrs <- forM (zip scanOpNe tys) $ \(ne, ty) ->-                  dPrimV "aggr" $ TPrimExp $ toExp' ty ne-                flag <- dPrimV "flag" (statusX :: Imp.TExp Int8)-                everythingVolatile . sWhen (tvExp readI .>=. 0) $ do+                  -- execute warp-parallel reduction but only if the last read flag in not STATUS_P+                  copyDWIMFix (tvVar flag) [] (Var warpscan) [sExt64 warpSize - 1]+                  sWhen (tvExp flag .<. (2 :: Imp.TExp Int8)) $ do+                    lam' <- renameLambda scan_op1+                    inBlockScanLookback+                      constants+                      num_virt_threads+                      warpscan+                      exchanges+                      lam'++                  -- all threads of the warp read the result of reduction+                  copyDWIMFix (tvVar flag) [] (Var warpscan) [sExt64 warpSize - 1]+                  forM_ (zip aggrs exchanges) $ \(aggr, exchange) ->+                    copyDWIMFix (tvVar aggr) [] (Var exchange) [sExt64 warpSize - 1]+                  -- update read offset                   sIf-                    (sameSegment readI)-                    ( do-                        copyDWIMFix (tvVar flag) [] (Var statusFlags) [sExt64 $ tvExp readI]-                        sIf-                          (tvExp flag .==. statusP)-                          ( forM_ (zip incprefixArrays aggrs) $ \(incprefix, aggr) ->-                              copyDWIMFix (tvVar aggr) [] (Var incprefix) [sExt64 $ tvExp readI]-                          )-                          ( sWhen (tvExp flag .==. statusA) $ do-                              forM_ (zip aggrs aggregateArrays) $ \(aggr, aggregate) ->-                                copyDWIMFix (tvVar aggr) [] (Var aggregate) [sExt64 $ tvExp readI]-                          )+                    (tvExp flag .==. statusP)+                    (readOffset <-- loopStop)+                    ( sWhen (tvExp flag .==. statusA) $ do+                        readOffset <-- tvExp readOffset - zExt32 warpSize                     )-                    (copyDWIMFix (tvVar flag) [] (intConst Int8 statusP) [])-                -- end sIf-                -- end sWhen -                forM_ (zip exchanges aggrs) $ \(exchange, aggr) ->-                  copyDWIMFix exchange [sExt64 $ kernelLocalThreadId constants] (tvSize aggr) []-                copyDWIMFix warpscan [sExt64 $ kernelLocalThreadId constants] (tvSize flag) []--                -- execute warp-parallel reduction but only if the last read flag in not STATUS_P-                copyDWIMFix (tvVar flag) [] (Var warpscan) [sExt64 warpSize - 1]-                sWhen (tvExp flag .<. (2 :: Imp.TExp Int8)) $ do-                  lam' <- renameLambda scanOp'-                  inBlockScanLookback-                    constants-                    num_threads-                    warpscan-                    exchanges-                    lam'--                -- all threads of the warp read the result of reduction-                copyDWIMFix (tvVar flag) [] (Var warpscan) [sExt64 warpSize - 1]-                forM_ (zip aggrs exchanges) $ \(aggr, exchange) ->-                  copyDWIMFix (tvVar aggr) [] (Var exchange) [sExt64 warpSize - 1]-                -- update read offset-                sIf-                  (tvExp flag .==. statusP)-                  (readOffset <-- loopStop)-                  ( sWhen (tvExp flag .==. statusA) $ do-                      readOffset <-- tvExp readOffset - zExt32 warpSize-                  )+                  -- update prefix if flag different than STATUS_X:+                  sWhen (tvExp flag .>. (statusX :: Imp.TExp Int8)) $ do+                    lam <- renameLambda scan_op1+                    let (xs, ys) = splitAt (length tys) $ map paramName $ lambdaParams lam+                    forM_ (zip xs aggrs) $ \(x, aggr) -> dPrimV_ x (tvExp aggr)+                    forM_ (zip ys prefixes) $ \(y, prefix) -> dPrimV_ y (tvExp prefix)+                    compileStms mempty (bodyStms $ lambdaBody lam) $+                      forM_ (zip3 prefixes tys $ map resSubExp $ bodyResult $ lambdaBody lam) $+                        \(prefix, ty, res) -> prefix <-- TPrimExp (toExp' ty res)+                  sOp local_fence+            ) -                -- update prefix if flag different than STATUS_X:-                sWhen (tvExp flag .>. (statusX :: Imp.TExp Int8)) $ do-                  lam <- renameLambda scanOp'-                  let (xs, ys) = splitAt (length tys) $ map paramName $ lambdaParams lam-                  forM_ (zip xs aggrs) $ \(x, aggr) -> dPrimV_ x (tvExp aggr)-                  forM_ (zip ys prefixes) $ \(y, prefix) -> dPrimV_ y (tvExp prefix)-                  compileStms mempty (bodyStms $ lambdaBody lam) $-                    forM_ (zip3 prefixes tys $ map resSubExp $ bodyResult $ lambdaBody lam) $-                      \(prefix, ty, res) -> prefix <-- TPrimExp (toExp' ty res)-                sOp localFence-          )+          -- end sWhile+          -- end sIf+          sWhen (kernelLocalThreadId constants .==. 0) $ do+            scan_op2 <- renameLambda scan_op1+            let xs = map paramName $ take (length tys) $ lambdaParams scan_op2+                ys = map paramName $ drop (length tys) $ lambdaParams scan_op2+            sWhen (boundary .==. sExt32 (group_size_e * chunk)) $ do+              forM_ (zip xs prefixes) $ \(x, prefix) -> dPrimV_ x $ tvExp prefix+              forM_ (zip ys accs) $ \(y, acc) -> dPrimV_ y $ tvExp acc+              compileStms mempty (bodyStms $ lambdaBody scan_op2) $+                everythingVolatile $+                  forM_ (zip incprefixArrays $ map resSubExp $ bodyResult $ lambdaBody scan_op2) $+                    \(incprefixArray, res) -> copyDWIMFix incprefixArray [tvExp dyn_id] res []+              sOp global_fence+              everythingVolatile $ copyDWIMFix statusFlags [tvExp dyn_id] (intConst Int8 statusP) []+            forM_ (zip exchanges prefixes) $ \(exchange, prefix) ->+              copyDWIMFix exchange [0] (tvSize prefix) []+            forM_ (zip3 accs tys scanop_nes) $ \(acc, ty, ne) ->+              tvVar acc <~~ toExp' ty ne+        -- end sWhen+        -- end sWhen -        -- end sWhile-        -- end sIf-        sWhen (kernelLocalThreadId constants .==. 0) $ do-          scanOp'''' <- renameLambda scanOp'-          let xs = map paramName $ take (length tys) $ lambdaParams scanOp''''-              ys = map paramName $ drop (length tys) $ lambdaParams scanOp''''-          sWhen (boundary .==. sExt32 (group_size' * m)) $ do-            forM_ (zip xs prefixes) $ \(x, prefix) -> dPrimV_ x $ tvExp prefix-            forM_ (zip ys accs) $ \(y, acc) -> dPrimV_ y $ tvExp acc-            compileStms mempty (bodyStms $ lambdaBody scanOp'''') $-              everythingVolatile $-                forM_ (zip incprefixArrays $ map resSubExp $ bodyResult $ lambdaBody scanOp'''') $-                  \(incprefixArray, res) -> copyDWIMFix incprefixArray [tvExp dynamicId] res []-            sOp globalFence-            everythingVolatile $ copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []+        sWhen (bNot $ tvExp dyn_id .==. 0) $ do+          sOp local_barrier           forM_ (zip exchanges prefixes) $ \(exchange, prefix) ->-            copyDWIMFix exchange [0] (tvSize prefix) []-          forM_ (zip3 accs tys scanOpNe) $ \(acc, ty, ne) ->-            tvVar acc <~~ toExp' ty ne-      -- end sWhen+            copyDWIMFix (tvVar prefix) [] (Var exchange) [0]+          sOp local_barrier       -- end sWhen--      sWhen (bNot $ tvExp dynamicId .==. 0) $ do-        sOp localBarrier-        forM_ (zip exchanges prefixes) $ \(exchange, prefix) ->-          copyDWIMFix (tvVar prefix) [] (Var exchange) [0]-        sOp localBarrier-    -- end sWhen-    -- end sComment--    scanOp''''' <- renameLambda scanOp'-    scanOp'''''' <- renameLambda scanOp'+      -- end sComment -    sComment "Distribute results" $ do-      let (xs, ys) = splitAt (length tys) $ map paramName $ lambdaParams scanOp'''''-          (xs', ys') = splitAt (length tys) $ map paramName $ lambdaParams scanOp''''''+      scan_op3 <- renameLambda scan_op1+      scan_op4 <- renameLambda scan_op1 -      forM_ (zip4 (zip prefixes accs) (zip xs xs') (zip ys ys') tys) $-        \((prefix, acc), (x, x'), (y, y'), ty) -> do-          dPrim_ x ty-          dPrim_ y ty-          dPrimV_ x' $ tvExp prefix-          dPrimV_ y' $ tvExp acc+      sComment "Distribute results" $ do+        let (xs, ys) = splitAt (length tys) $ map paramName $ lambdaParams scan_op3+            (xs', ys') = splitAt (length tys) $ map paramName $ lambdaParams scan_op4 -      sIf-        (kernelLocalThreadId constants * m .<. boundary .&&. bNot blockNewSgm)-        ( compileStms mempty (bodyStms $ lambdaBody scanOp'''''') $-            forM_ (zip3 xs tys $ map resSubExp $ bodyResult $ lambdaBody scanOp'''''') $-              \(x, ty, res) -> x <~~ toExp' ty res-        )-        (forM_ (zip xs accs) $ \(x, acc) -> copyDWIMFix x [] (Var $ tvVar acc) [])-      -- calculate where previous thread stopped, to determine number of-      -- elements left before new segment.-      stop <--        dPrimVE "stopping_point" $-          segsize_compact - (kernelLocalThreadId constants * m - 1 + segsize_compact - boundary) `rem` segsize_compact-      sFor "i" m $ \i -> do-        sWhen (sExt32 i .<. stop - 1) $ do-          forM_ (zip privateArrays ys) $ \(src, y) ->-            -- only include prefix for the first segment part per thread-            copyDWIMFix y [] (Var src) [i]-          compileStms mempty (bodyStms $ lambdaBody scanOp''''') $-            forM_ (zip privateArrays $ map resSubExp $ bodyResult $ lambdaBody scanOp''''') $-              \(dest, res) ->-                copyDWIMFix dest [i] res []+        forM_ (zip7 prefixes accs xs xs' ys ys' tys) $+          \(prefix, acc, x, x', y, y', ty) -> do+            dPrim_ x ty+            dPrim_ y ty+            dPrimV_ x' $ tvExp prefix+            dPrimV_ y' $ tvExp acc -    sComment "Transpose scan output and Write it to global memory in coalesced fashion" $ do-      forM_ (zip3 transposedArrays privateArrays $ map patElemName all_pes) $ \(locmem, priv, dest) -> do-        -- sOp localBarrier-        sFor "i" m $ \i -> do-          sharedIdx <--            dPrimV "sharedIdx" $-              sExt64 (kernelLocalThreadId constants * m) + i-          copyDWIMFix locmem [tvExp sharedIdx] (Var priv) [i]-        sOp localBarrier-        sFor "i" m $ \i -> do-          flat_idx <--            dPrimVE "flat_idx" $-              tvExp blockOff-                + kernelGroupSize constants * i-                + sExt64 (kernelLocalThreadId constants)-          dIndexSpace (zip gtids dims') flat_idx-          sWhen (flat_idx .<. n) $ do-            copyDWIMFix-              dest-              (map Imp.le64 gtids)-              (Var locmem)-              [sExt64 $ flat_idx - tvExp blockOff]-        sOp localBarrier+        sIf+          (kernelLocalThreadId constants * chunk .<. boundary .&&. bNot blockNewSgm)+          ( compileStms mempty (bodyStms $ lambdaBody scan_op4) $+              forM_ (zip3 xs tys $ map resSubExp $ bodyResult $ lambdaBody scan_op4) $+                \(x, ty, res) -> x <~~ toExp' ty res+          )+          (forM_ (zip xs accs) $ \(x, acc) -> copyDWIMFix x [] (Var $ tvVar acc) [])+        -- calculate where previous thread stopped, to determine number of+        -- elements left before new segment.+        stop <-+          dPrimVE "stopping_point" $+            segsize_compact - (kernelLocalThreadId constants * chunk - 1 + segsize_compact - boundary) `rem` segsize_compact+        sFor "i" chunk $ \i -> do+          sWhen (sExt32 i .<. stop - 1) $ do+            forM_ (zip privateArrays ys) $ \(src, y) ->+              -- only include prefix for the first segment part per thread+              copyDWIMFix y [] (Var src) [i]+            compileStms mempty (bodyStms $ lambdaBody scan_op3) $+              forM_ (zip privateArrays $ map resSubExp $ bodyResult $ lambdaBody scan_op3) $+                \(dest, res) ->+                  copyDWIMFix dest [i] res [] -    sComment "If this is the last block, reset the dynamicId" $-      sWhen (tvExp dynamicId .==. num_groups' - 1) $-        copyDWIMFix globalId [0] (constant (0 :: Int32)) []+      sComment "Transpose scan output and Write it to global memory in coalesced fashion" $ do+        forM_ (zip3 transposedArrays privateArrays $ map patElemName all_pes) $ \(locmem, priv, dest) -> do+          -- sOp local_barrier+          sFor "i" chunk $ \i -> do+            sharedIdx <-+              dPrimV "sharedIdx" $+                sExt64 (kernelLocalThreadId constants * chunk) + i+            copyDWIMFix locmem [tvExp sharedIdx] (Var priv) [i]+          sOp local_barrier+          sFor "i" chunk $ \i -> do+            flat_idx <-+              dPrimVE "flat_idx" $+                tvExp blockOff+                  + kernelGroupSize constants * i+                  + sExt64 (kernelLocalThreadId constants)+            dIndexSpace (zip gtids dims') flat_idx+            sWhen (flat_idx .<. n) $ do+              copyDWIMFix+                dest+                (map Imp.le64 gtids)+                (Var locmem)+                [sExt64 $ flat_idx - tvExp blockOff]+          sOp local_barrier {-# NOINLINE compileSegScan #-}
src/Futhark/IR/SOACS/SOAC.hs view
@@ -627,18 +627,19 @@     let deps = lambdaDependencies mempty lam (depsOfArrays w arrs)      in map flattenGroups (groupScatterResults outputs deps)     where-      flattenGroups (_, _, ivs) =-        mconcat (map (mconcat . fst) ivs) <> mconcat (map snd ivs)+      flattenGroups (_, arr, ivs) =+        oneName arr <> mconcat (map (mconcat . fst) ivs) <> mconcat (map snd ivs)   opDependencies (JVP lam args vec) =     mconcat $       replicate 2 $         lambdaDependencies mempty lam $           zipWith (<>) (map depsOf' args) (map depsOf' vec)   opDependencies (VJP lam args vec) =-    mconcat $-      replicate 2 $-        lambdaDependencies mempty lam $-          zipWith (<>) (map depsOf' args) (map depsOf' vec)+    lambdaDependencies+      mempty+      lam+      (zipWith (<>) (map depsOf' args) (map depsOf' vec))+      <> map (const $ freeIn args <> freeIn lam) (lambdaParams lam)   opDependencies (Screma w arrs (ScremaForm scans reds map_lam)) =     let (scans_in, reds_in, map_deps) =           splitAt3 (scanResults scans) (redResults reds) $
src/Futhark/IR/SegOp.hs view
@@ -844,11 +844,11 @@     inside "SegMap" $ kernelBodyMetrics body   opMetrics (SegRed _ _ reds _ body) =     inside "SegRed" $ do-      mapM_ (lambdaMetrics . segBinOpLambda) reds+      mapM_ (inside "SegBinOp" . lambdaMetrics . segBinOpLambda) reds       kernelBodyMetrics body   opMetrics (SegScan _ _ scans _ body) =     inside "SegScan" $ do-      mapM_ (lambdaMetrics . segBinOpLambda) scans+      mapM_ (inside "SegBinOp" . lambdaMetrics . segBinOpLambda) scans       kernelBodyMetrics body   opMetrics (SegHist _ _ ops _ body) =     inside "SegHist" $ do@@ -1275,7 +1275,9 @@     (red_ts, map_ts) = splitAt (segBinOpResults ops) ts     (red_res, map_res) = splitAt (segBinOpResults ops) $ kernelBodyResult kbody -    sameShape (op1, _) (op2, _) = segBinOpShape op1 == segBinOpShape op2+    sameShape (op1, _) (op2, _) =+      segBinOpShape op1 == segBinOpShape op2+        && shapeRank (segBinOpShape op1) > 0      combineOps [] = Nothing     combineOps (x : xs) = Just $ foldl' combine x xs
src/Futhark/Optimise/Simplify/Engine.hs view
@@ -680,7 +680,9 @@                  && loopInvariantStm vtable stm                  -- Avoid hoisting out something that might change the                  -- asymptotics of the program.-                 && all primType (patTypes (stmPat stm))+                 && ( all primType (patTypes (stmPat stm))+                        || (ifsort == MatchEquiv && isManifest (stmExp stm))+                    )              )           || ( ifsort /= MatchFallback                  && any (`UT.isSize` usage) (patNames (stmPat stm))@@ -703,6 +705,9 @@       isNotHoistableBnd _ _ _ =         -- Hoist aggressively out of versioning branches.         ifsort /= MatchEquiv++      isManifest (BasicOp Manifest {}) = True+      isManifest _ = False        block =         branch_blocker
src/Futhark/Pass/ExtractKernels/Intragroup.hs view
@@ -253,6 +253,8 @@             =<< runDistNestT env (distributeMapBodyStms acc (bodyStms $ lambdaBody lam))     Op (Screma w arrs form)       | Just (scans, mapfun) <- isScanomapSOAC form,+        -- FIXME: Futhark.CodeGen.ImpGen.GPU.Group.compileGroupOp+        -- cannot handle multiple scan operators yet.         Scan scanfun nes <- singleScan scans -> do           let scanfun' = soacsLambdaToGPU scanfun               mapfun' = soacsLambdaToGPU mapfun@@ -260,12 +262,13 @@             addStms =<< segScan lvl pat mempty w [SegBinOp Noncommutative scanfun' nes mempty] mapfun' arrs [] []           parallelMin [w]     Op (Screma w arrs form)-      | Just (reds, map_lam) <- isRedomapSOAC form,-        Reduce comm red_lam nes <- singleReduce reds -> do-          let red_lam' = soacsLambdaToGPU red_lam+      | Just (reds, map_lam) <- isRedomapSOAC form -> do+          let onReduce (Reduce comm red_lam nes) =+                SegBinOp comm (soacsLambdaToGPU red_lam) nes mempty+              reds' = map onReduce reds               map_lam' = soacsLambdaToGPU map_lam           certifying (stmAuxCerts aux) $-            addStms =<< segRed lvl pat mempty w [SegBinOp comm red_lam' nes mempty] map_lam' arrs [] []+            addStms =<< segRed lvl pat mempty w reds' map_lam' arrs [] []           parallelMin [w]     Op (Screma w arrs form) ->       -- This screma is too complicated for us to immediately do
src/Futhark/Util/CMath.hs view
@@ -22,9 +22,13 @@     cbrtf,     hypot,     hypotf,+    ldexp,+    ldexpf,   ) where +import Foreign.C.Types (CInt (..))+ foreign import ccall "nearbyint" c_nearbyint :: Double -> Double  foreign import ccall "nearbyintf" c_nearbyintf :: Float -> Float@@ -146,3 +150,15 @@ -- | The system-level @cbrtf@ function. cbrtf :: Float -> Float cbrtf = c_cbrtf++foreign import ccall "ldexp" c_ldexp :: Double -> CInt -> Double++foreign import ccall "ldexpf" c_ldexpf :: Float -> CInt -> Float++-- | The system-level @ldexp@ function.+ldexp :: Double -> CInt -> Double+ldexp = c_ldexp++-- | The system-level @ldexpf@ function.+ldexpf :: Float -> CInt -> Float+ldexpf = c_ldexpf
src/Language/Futhark/Parser/Lexer.x view
@@ -90,8 +90,6 @@   "$"                      { tokenC DOLLAR }   "???"                    { tokenC HOLE } -  @declit                  { \s -> decToken (NATLIT (nameFromBS s)) s }-   @declit i8               { decToken I8LIT . BS.dropEnd 2 }   @binlit i8               { binToken I8LIT . BS.drop 2 . BS.dropEnd 2 }   @hexlit i8               { hexToken I8LIT . BS.drop 2 . BS.dropEnd 2 }@@ -132,7 +130,7 @@   @hexlit u64              { hexToken U64LIT . BS.drop 2 . BS.dropEnd 3 }   @romlit u64              { romToken U64LIT . BS.drop 2 . BS.dropEnd 3 } -  @declit                  { decToken INTLIT }+  @declit                  { \s -> decToken (NATLIT (nameFromBS s)) s }   @binlit                  { binToken INTLIT . BS.drop 2 }   @hexlit                  { hexToken INTLIT . BS.drop 2 }   @romlit                  { romToken INTLIT . BS.drop 2 }
src/Language/Futhark/Parser/Parser.y view
@@ -163,12 +163,11 @@       hole            { L $$ HOLE }  %left bottom-%left typeprec %left ifprec letprec caseprec typeprec enumprec sumprec %left ',' case id constructor '(' '{' %right ':' ':>' %right '...' '..<' '..>' '..'-%left '`' '!...'+%left '`' %right '->' %left with %left '='
src/Language/Futhark/Primitive.hs view
@@ -1271,6 +1271,34 @@       f32_2 "nextafter32" nextafterf,       f64_2 "nextafter64" nextafter,       --+      ( "ldexp16",+        ( [FloatType Float16, IntType Int32],+          FloatType Float16,+          \case+            [FloatValue (Float16Value x), IntValue (Int32Value y)] ->+              Just $ FloatValue $ Float16Value $ x * (2 ** fromIntegral y)+            _ -> Nothing+        )+      ),+      ( "ldexp32",+        ( [FloatType Float32, IntType Int32],+          FloatType Float32,+          \case+            [FloatValue (Float32Value x), IntValue (Int32Value y)] ->+              Just $ FloatValue $ Float32Value $ x * (2 ** fromIntegral y)+            _ -> Nothing+        )+      ),+      ( "ldexp64",+        ( [FloatType Float64, IntType Int32],+          FloatType Float64,+          \case+            [FloatValue (Float64Value x), IntValue (Int32Value y)] ->+              Just $ FloatValue $ Float64Value $ x * (2 ** fromIntegral y)+            _ -> Nothing+        )+      ),+      --       f16 "gamma16" $ convFloat . tgammaf . convFloat,       f32 "gamma32" tgammaf,       f64 "gamma64" tgamma,