futhark 0.25.14 → 0.25.15
raw patch · 13 files changed
+122/−38 lines, 13 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +17/−0
- futhark.cabal +1/−1
- rts/c/backends/cuda.h +1/−1
- rts/c/event_list.h +8/−3
- rts/c/server.h +11/−1
- src/Futhark/CodeGen/Backends/GenericC.hs +7/−3
- src/Futhark/CodeGen/Backends/SimpleRep.hs +23/−7
- src/Futhark/IR/SegOp.hs +1/−5
- src/Futhark/Internalise/Entry.hs +1/−0
- src/Futhark/Optimise/Simplify/Rules/Index.hs +25/−0
- src/Futhark/Pass/ExtractKernels.hs +14/−14
- src/Language/Futhark/Prop.hs +10/−2
- src/Language/Futhark/TypeChecker/Unify.hs +3/−1
CHANGELOG.md view
@@ -5,6 +5,23 @@ 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.15]++### Added++* Incremental Flattening generates fewer redundant code versions.++* Better simplification of slices. (#2125)++### Fixed++* Ignore type suffixes when unifying expressions (#2124).++* In the C API, opaque types that correspond to an array of an opaque+ type are now once again named `futhark_opaque_arr_...`.++* `cuda` backend did not correctly profile CPU-to-GPU scalar copies.+ ## [0.25.14] ### Added
futhark.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: futhark-version: 0.25.14+version: 0.25.15 synopsis: An optimising compiler for a functional, array-oriented language. description: Futhark is a small programming language designed to be compiled to
rts/c/backends/cuda.h view
@@ -942,7 +942,7 @@ } CUDA_SUCCEED_OR_RETURN(cuMemcpyHtoD(dst + offset, src, size)); if (event != NULL) {- CUDA_SUCCEED_FATAL(cuEventRecord(event->start, ctx->stream));+ CUDA_SUCCEED_FATAL(cuEventRecord(event->end, ctx->stream)); } return FUTHARK_SUCCESS; }
rts/c/event_list.h view
@@ -41,8 +41,9 @@ l->num_events++; } -static void report_events_in_list(struct event_list *l,- struct str_builder* sb) {+static int report_events_in_list(struct event_list *l,+ struct str_builder* sb) {+ int ret = 0; for (int i = 0; i < l->num_events; i++) { if (i != 0) { str_builder_str(sb, ",");@@ -52,11 +53,15 @@ str_builder_str(sb, ",\"description\":"); str_builder_json_str(sb, l->events[i].description); free(l->events[i].description);- l->events[i].f(sb, l->events[i].data);+ if (l->events[i].f(sb, l->events[i].data) != 0) {+ ret = 1;+ break;+ } str_builder(sb, "}"); } event_list_free(l); event_list_init(l);+ return ret; } // End of event_list.h
rts/c/server.h view
@@ -553,7 +553,17 @@ void cmd_report(struct server_state *s, const char *args[]) { (void)args; char *report = futhark_context_report(s->ctx);- puts(report);+ if (report) {+ puts(report);+ } else {+ failure();+ report = futhark_context_get_error(s->ctx);+ if (report) {+ puts(report);+ } else {+ puts("Failed to produce profiling report.\n");+ }+ } free(report); }
src/Futhark/CodeGen/Backends/GenericC.hs view
@@ -650,9 +650,13 @@ str_builder_str(&builder, "\"memory\":{"); $items:(L.intersperse comma memreport) str_builder_str(&builder, "},\"events\":[");- report_events_in_list(&ctx->event_list, &builder);- str_builder_str(&builder, "]}");- return builder.str;+ if (report_events_in_list(&ctx->event_list, &builder) != 0) {+ free(builder.str);+ return NULL;+ } else {+ str_builder_str(&builder, "]}");+ return builder.str;+ } }|] )
src/Futhark/CodeGen/Backends/SimpleRep.hs view
@@ -40,7 +40,7 @@ import Data.Text qualified as T import Futhark.CodeGen.ImpCode import Futhark.CodeGen.RTS.C (scalarF16H, scalarH)-import Futhark.Util (hashText, zEncodeText)+import Futhark.Util (hashText, showText, zEncodeText) import Language.C.Quote.C qualified as C import Language.C.Syntax qualified as C @@ -123,18 +123,34 @@ | isValidCName v = v | otherwise = zEncodeText v +-- | Valid C identifier name?+valid :: T.Text -> Bool+valid s =+ T.head s /= '_'+ && not (isDigit $ T.head s)+ && T.all ok s+ where+ ok c = isAlphaNum c || c == '_'++isArrayName :: T.Text -> (Int, T.Text)+isArrayName s =+ if "[]" `T.isPrefixOf` s+ then+ let (k, s') = isArrayName (T.drop 2 s)+ in (k + 1, s')+ else (0, s)+ -- | The name of exposed opaque types. opaqueName :: Name -> T.Text opaqueName "()" = "opaque_unit" -- Hopefully this ad-hoc convenience won't bite us. opaqueName s- | valid = "opaque_" <> s'+ | (k, s'') <- isArrayName s',+ k > 0,+ valid s'' =+ "opaque_arr_" <> s'' <> "_" <> showText k <> "d"+ | valid s' = "opaque_" <> s' where s' = nameToText s- valid =- T.head s' /= '_'- && not (isDigit $ T.head s')- && T.all ok s'- ok c = isAlphaNum c || c == '_' opaqueName s = "opaque_" <> hashText (nameToText s) -- | The 'PrimType' (and sign) correspond to a human-readable scalar
src/Futhark/IR/SegOp.hs view
@@ -1230,11 +1230,7 @@ when (kres == kres') cannotSimplify kbody <- mkKernelBodyM kstms kres'- addStm $- Let (Pat kpes') dec $- Op $- segOp $- SegMap lvl space ts' kbody+ addStm $ Let (Pat kpes') dec $ Op $ segOp $ SegMap lvl space ts' kbody where isInvariant Constant {} = True isInvariant (Var v) = isJust $ ST.lookup v vtable
src/Futhark/Internalise/Entry.hs view
@@ -51,6 +51,7 @@ rootType (E.TEApply te E.TypeArgExpSize {} _) = rootType te rootType (E.TEUnique te _) = rootType te rootType (E.TEDim _ te _) = rootType te+rootType (E.TEParens te _) = rootType te rootType te = te typeExpOpaqueName :: E.TypeExp E.Exp VName -> Name
src/Futhark/Optimise/Simplify/Rules/Index.hs view
@@ -7,6 +7,7 @@ ) where +import Control.Monad (guard) import Data.List.NonEmpty (NonEmpty (..)) import Data.Maybe import Futhark.Analysis.PrimExp.Convert@@ -31,6 +32,14 @@ = IndexResult Certs VName (Slice SubExp) | SubExpResult Certs SubExp +-- Fake expressions that we can recognise.+fakeIndices :: [TPrimExp Int64 VName]+fakeIndices = map f [0 :: Int ..]+ where+ f i = isInt64 $ LeafExp (VName v (negate i)) $ IntType Int64+ where+ v = nameFromText ("fake_" <> showText i)+ -- | Try to simplify an index operation. simplifyIndexing :: (MonadBuilder m) =>@@ -60,6 +69,22 @@ Just $ IndexResult cs arr . Slice . map DimFix <$> mapM (toSubExp "index_primexp") inds''+ | Just (ST.IndexedArray cs arr inds'') <-+ ST.index' idd (fixSlice (pe64 <$> Slice inds) (map fst matches)) vtable,+ all (worthInlining . untyped) inds'',+ arr `ST.available` vtable,+ all (`ST.elem` vtable) (unCerts cs),+ Just inds''' <- mapM okIdx inds'' -> do+ Just $ IndexResult cs arr . Slice <$> sequence inds'''+ where+ matches = zip fakeIndices $ sliceDims $ Slice inds+ okIdx i =+ case lookup i matches of+ Just w ->+ Just $ pure $ DimSlice (constant (0 :: Int64)) w (constant (1 :: Int64))+ Nothing -> do+ guard $ not $ any ((`namesIntersect` freeIn i) . freeIn . fst) matches+ Just $ DimFix <$> toSubExp "index_primexp" i Nothing -> Nothing Just (SubExp (Var v), cs) -> Just $ pure $ IndexResult cs v $ Slice inds
src/Futhark/Pass/ExtractKernels.hs view
@@ -619,34 +619,34 @@ -- | A lambda is worth sequentialising if it contains enough nested -- parallelism of an interesting kind. worthSequentialising :: Lambda SOACS -> Bool-worthSequentialising lam = bodyInterest (lambdaBody lam) > 1+worthSequentialising lam = bodyInterest (0 :: Int) (lambdaBody lam) > 1 where- bodyInterest body =- sum $ interest <$> bodyStms body- interest stm+ bodyInterest depth body =+ sum $ interest depth <$> bodyStms body+ interest depth stm | "sequential" `inAttrs` attrs = 0 :: Int | Op (Screma _ _ form@(ScremaForm _ _ lam')) <- stmExp stm, isJust $ isMapSOAC form = if sequential_inner then 0- else bodyInterest (lambdaBody lam')+ else bodyInterest (depth + 1) (lambdaBody lam') | Op Scatter {} <- stmExp stm = 0 -- Basically a map. | Loop _ ForLoop {} body <- stmExp stm =- bodyInterest body * 10+ bodyInterest (depth + 1) body * 10 | WithAcc _ withacc_lam <- stmExp stm =- bodyInterest (lambdaBody withacc_lam)+ bodyInterest (depth + 1) (lambdaBody withacc_lam) | Op (Screma _ _ form@(ScremaForm _ _ lam')) <- stmExp stm = 1- + bodyInterest (lambdaBody lam')+ + bodyInterest (depth + 1) (lambdaBody lam') +- -- Give this a bigger score if it's a redomap, as these- -- are often tileable and thus benefit more from- -- sequentialisation.- case isRedomapSOAC form of- Just _ -> 1- Nothing -> 0+ -- Give this a bigger score if it's a redomap just inside+ -- the the outer lambda, as these are often tileable and+ -- thus benefit more from sequentialisation.+ case (isRedomapSOAC form, depth) of+ (Just _, 0) -> 1+ _ -> 0 | otherwise = 0 where
src/Language/Futhark/Prop.hs view
@@ -1376,12 +1376,20 @@ -- | If these two expressions are structurally similar at top level as -- sizes, produce their subexpressions (which are not necessarily--- similar, but you can check for that!). This is the machinery--- underlying expresssion unification.+-- similar, but you can check for that!). This is the machinery+-- underlying expresssion unification. We assume that the expressions+-- have the same type. similarExps :: Exp -> Exp -> Maybe [(Exp, Exp)] similarExps e1 e2 | bareExp e1 == bareExp e2 = Just [] similarExps e1 e2 | Just e1' <- stripExp e1 = similarExps e1' e2 similarExps e1 e2 | Just e2' <- stripExp e2 = similarExps e1 e2'+similarExps (IntLit x _ _) (Literal v _) =+ case v of+ SignedValue (Int8Value y) | x == toInteger y -> Just []+ SignedValue (Int16Value y) | x == toInteger y -> Just []+ SignedValue (Int32Value y) | x == toInteger y -> Just []+ SignedValue (Int64Value y) | x == toInteger y -> Just []+ _ -> Nothing similarExps (AppExp (BinOp (op1, _) _ (x1, _) (y1, _) _) _) (AppExp (BinOp (op2, _) _ (x2, _) (y2, _) _) _)
src/Language/Futhark/TypeChecker/Unify.hs view
@@ -1152,8 +1152,10 @@ pure (t, M.elems seen) where r = RigidCond t1 t2+ same (e1, e2) =+ maybe False (all same) $ similarExps e1 e2 onDims _ d1 d2- | d1 == d2 = pure d1+ | same (d1, d2) = pure d1 | otherwise = do -- Remember mismatches we have seen before and reuse the -- same new size.