Skip to content

Commit

Permalink
1st March 2024: this works with the corresponding Accelerate/new-pipe…
Browse files Browse the repository at this point in the history
…line commit
  • Loading branch information
dpvanbalen committed Mar 1, 2024
1 parent 6339274 commit 263f8a3
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ codegen uid env (Clustered c b) args =
workstealLoop workstealIndex workstealActiveThreads (op scalarTypeInt32 $ constant (TupRsingle scalarTypeInt32) 1) $ \_ -> do
let b' = mapArgs BCAJA b
(acc, loopsize') <- execStateT (evalCluster (toOnlyAcc c) b' args gamma ()) (mempty, LS ShapeRz OP_Unit)
Debug.Trace.traceShow loopsize' $ return ()
body acc loopsize'
retval_ $ boolean True
where
Expand All @@ -118,7 +119,15 @@ codegen uid env (Clustered c b) args =
-- (ShapeRz,_) -> error "tiny cluster"
-- (ShapeRsnoc shr', OP_Pair sh' sz) ->
(shr', sh') ->
evalStateT (go shr' sh' (1, constant typerInt 0, [])) initialAcc
flip evalStateT initialAcc $ do
-- we add one more layer here, for writing scalars -- e.g. the output of a fold over a vector
go shr' sh' (1, constant typerInt 0, [])
let ba = makeBackendArg @NativeOp args gamma c b
let i = (0, constant typerInt 0 ,[])
newInputs <- readInputs @_ @_ @NativeOp i args ba gamma
outputs <- evalOps @NativeOp i c newInputs args gamma
writeOutputs @_ @_ @NativeOp i args outputs gamma

iter' :: Operands Int
-> (Int, Operands Int, [Operands Int])
-> ((Int, Operands Int, [Operands Int]) -> StateT Accumulated (CodeGen Native) ()) -> StateT Accumulated (CodeGen Native) ()
Expand Down Expand Up @@ -219,15 +228,16 @@ instance EvalOp NativeOp where
subtup (SubTupRpair a b) (CJ (OP_Pair x y)) = CJ $ OP_Pair ((\(CJ z)->z) $ subtup @NativeOp a $ CJ x) ((\(CJ z)->z) $ subtup @NativeOp b $ CJ y)

-- the scalartypes guarantee that there is always only one buffer, and that the unsafeCoerce from (Buffers e) to (Buffer e) is safe
writeOutput tp sh ~(TupRsingle buf) gamma (d,i,_) = \case
writeOutput tp sh (TupRsingle buf) gamma (d,i,_) = \case
CN -> pure ()
CJ x -> lift $ Prelude.when (sh `isAtDepth` d) $ writeBuffer tp TypeInt (aprjBuffer (unsafeCoerce buf) gamma) (op TypeInt i) (op tp x)
writeOutput _ _ _ _ _ = error "not single"
readInput :: forall e env sh. ScalarType e -> GroundVars env sh -> GroundVars env (Buffers e) -> Gamma env -> BackendClusterArg2 NativeOp env (In sh e) -> (Int, Operands Int, [Operands Int]) -> StateT Accumulated (CodeGen Native) (Compose Maybe Operands e)
readInput _ _ _ _ _ (d,_,is) | d /= length is = error "fail"
readInput tp sh ~(TupRsingle buf) gamma (BCAN2 Nothing d') (d,i, _)
readInput tp sh (TupRsingle buf) gamma (BCAN2 Nothing d') (d,i, _)
| d /= d' = pure CN
| otherwise = lift $ CJ . ir tp <$> readBuffer tp TypeInt (aprjBuffer (unsafeCoerce buf) gamma) (op TypeInt i)
readInput tp sh ~(TupRsingle buf) gamma (BCAN2 (Just (BP shr1 (shr2 :: ShapeR sh2) f ls)) _) (d,_,ix)
readInput tp sh (TupRsingle buf) gamma (BCAN2 (Just (BP shr1 (shr2 :: ShapeR sh2) f ls)) _) (d,_,ix)
| Just Refl <- varsContainsThisShape sh shr2
, shr1 `isAtDepth'` d
= lift $ CJ . ir tp <$> do
Expand All @@ -237,6 +247,7 @@ instance EvalOp NativeOp where
i <- intOfIndex shr2 sh' sh2
readBuffer tp TypeInt (aprjBuffer (unsafeCoerce buf) gamma) (op TypeInt i)
| otherwise = pure CN
readInput _ _ _ _ _ _ = error "not single"

evalOp :: (Int, Operands Int, [Operands Int])
-> Label
Expand All @@ -251,9 +262,9 @@ instance EvalOp NativeOp where
_ -> pure CN
evalOp _ _ NBackpermute _ (Push (Push (Push Env.Empty (BAE (Shape' shr sh) _)) (BAE (Value' x _) _)) _)
= lift $ pure $ Push Env.Empty $ FromArg $ Value' x $ Shape' shr sh
evalOp (d',_,is) _ NGenerate gamma (Push (Push Env.Empty (BAE (Shape' shr ~(CJ sh)) _)) (BAE f (BCAN2 Nothing d)))
evalOp (d',_,is) _ NGenerate gamma (Push (Push Env.Empty (BAE (Shape' shr (CJ sh)) _)) (BAE f (BCAN2 Nothing d)))
| shr `isAtDepth'` d' = lift $ Push Env.Empty . FromArg . flip Value' (Shape' shr (CJ sh)) . CJ <$> app1 (llvmOfFun1 @Native f gamma) (multidim shr is)
| d' == d = error "how come we didn't hit the case above?"
| d' == d = error $ "how come we didn't hit the case above?" <> show (d', d, rank shr)
| otherwise = pure $ Push Env.Empty $ FromArg $ Value' CN (Shape' shr (CJ sh))
evalOp (d',_,is) _ NGenerate gamma (Push (Push Env.Empty (BAE (Shape' shr sh) _)) (BAE f (BCAN2 (Just (BP shrO shrI idxTransform ls)) d)))
| not $ shrO `isAtDepth'` d'
Expand Down Expand Up @@ -285,11 +296,12 @@ instance EvalOp NativeOp where
pure Env.Empty
| d == d' = error "case above?"
| otherwise = pure Env.Empty
evalOp (d',_,~(inner:_)) l NScanl1 gamma (Push (Push _ (BAE (Value' x' sh) (BCAN2 Nothing d))) (BAE f' _))
evalOp (d',_,ixs) l NScanl1 gamma (Push (Push _ (BAE (Value' x' sh) (BCAN2 Nothing d))) (BAE f' _))
| f <- llvmOfFun2 @Native f' gamma
, Lam (lhsToTupR -> ty :: TypeR e) _ <- f'
, CJ x <- x'
, d == d'
, inner:_ <- ixs
= StateT $ \acc -> do
let (Exists (unsafeCoerce @(Operands _) @(Operands e) -> accX), eTy) = acc M.! l
z <- ifThenElse (ty, eq singleType inner (constant typerInt 0)) (pure x) (app2 f accX x) -- note: need to apply the accumulator as the _left_ argument to the function
Expand All @@ -298,11 +310,12 @@ instance EvalOp NativeOp where
evalOp _ _ NScanl1 gamma (Push (Push _ (BAE (Value' x' sh) (BCAN2 (Just (BP{})) d))) (BAE f' _)) = error "backpermuted scan"
evalOp i l NFold1 gamma args = error "todo: fold1"
-- we can ignore the index permutation for folds here
evalOp (d',_,~(inner:_)) l NFold2 gamma (Push (Push _ (BAE (Value' x' sh@(Shape' (ShapeRsnoc shr') ~(CJ (OP_Pair sh' _)))) (BCAN2 _ d))) (BAE f' _))
evalOp (d',_,ixs) l NFold2 gamma (Push (Push _ (BAE (Value' x' sh@(Shape' (ShapeRsnoc shr') (CJ (OP_Pair sh' _)))) (BCAN2 _ d))) (BAE f' _))
| f <- llvmOfFun2 @Native f' gamma
, Lam (lhsToTupR -> ty :: TypeR e) _ <- f'
, CJ x <- x'
, d == d'
, inner:_ <- ixs
= StateT $ \acc -> do
let (Exists (unsafeCoerce @(Operands _) @(Operands e) -> accX), eTy) = acc M.! l
z <- ifThenElse (ty, eq singleType inner (constant typerInt 0)) (pure x) (app2 f accX x) -- note: need to apply the accumulator as the _left_ argument to the function
Expand All @@ -314,6 +327,7 @@ instance EvalOp NativeOp where
let (Exists (unsafeCoerce @(Operands _) @(Operands e) -> x), _) = acc M.! l
pure (Push Env.Empty $ FromArg (Value' (CJ x) (Shape' shr' (CJ sh'))), acc)
| otherwise = pure $ Push Env.Empty $ FromArg (Value' CN (Shape' shr' (CJ sh')))
-- evalOp _ _ _ _ _ = error "unmatched pattern?"

multidim :: ShapeR sh -> [Operands Int] -> Operands sh
multidim ShapeRz [] = OP_Unit
Expand Down Expand Up @@ -359,6 +373,9 @@ newtype JustAccumulator a b = JA (a b)
data Loopsizes where
LS :: ShapeR sh -> Operands sh -> Loopsizes

instance Show Loopsizes where
show (LS shr op) = "Loop of rank " <> show (rank shr)

merge :: Loopsizes -> GroundVars env sh -> Gamma env -> Loopsizes
merge ls v gamma = combine ls $ LS (gvarsToShapeR v) (aprjParameters (unsafeToExpVars v) gamma)

Expand Down Expand Up @@ -394,7 +411,7 @@ instance EvalOp (JustAccumulator NativeOp) where
type EnvF (JustAccumulator NativeOp) = GroundOperand

unit = TupRunit

embed = error "not needed"
indexsh vars _ = pure $ mapTupR varType $ unsafeToExpVars vars
indexsh' vars _ = pure $ mapTupR varType vars

Expand All @@ -406,7 +423,7 @@ instance EvalOp (JustAccumulator NativeOp) where
readInput ty sh _ gamma (BCA2JA (BCAN2 Nothing d)) _ = StateT $ \(acc,ls) -> pure (TupRsingle ty, (acc, merge ls sh gamma))
readInput ty sh _ gamma (BCA2JA (BCAN2 (Just (BP _ _ _ ls')) d)) _ = StateT $ \(acc,ls) -> pure (TupRsingle ty, (acc, merge ls ls' gamma))

writeOutput _ _ _ _ _ _ = pure ()
writeOutput ty sh buf gamma ix x = StateT $ \(acc,ls) -> pure ((), (acc, merge ls sh gamma))

evalOp () l (JA NScanl1) _ (Push (Push _ (BAE (Value' ty sh) _)) (BAE f _))
= StateT $ \(acc,ls) -> do
Expand Down Expand Up @@ -441,6 +458,7 @@ instance MakesILP op => MakesILP (JustAccumulator op) where
labelLabelledArg = undefined
getClusterArg = undefined
encodeBackendClusterArg = undefined
combineBackendClusterArg = undefined
-- probably just never running anything here
-- this is really just here because MakesILP is a superclass

Expand All @@ -452,6 +470,7 @@ instance (StaticClusterAnalysis op, EnvF (JustAccumulator op) ~ EnvF op) => Stat
valueToIn x = coerce @(BackendClusterArg2 op _ _) @(BackendClusterArg2 (JustAccumulator op) _ _) $ valueToIn $ coerce x
valueToOut x = coerce @(BackendClusterArg2 op _ _) @(BackendClusterArg2 (JustAccumulator op) _ _) $ valueToOut $ coerce x
inToValue x = coerce @(BackendClusterArg2 op _ _) @(BackendClusterArg2 (JustAccumulator op) _ _) $ inToValue $ coerce x
inToVar x = coerce @(BackendClusterArg2 op _ _) @(BackendClusterArg2 (JustAccumulator op) _ _) $ inToVar $ coerce x
outToValue x = coerce @(BackendClusterArg2 op _ _) @(BackendClusterArg2 (JustAccumulator op) _ _) $ outToValue $ coerce x
outToSh x = coerce @(BackendClusterArg2 op _ _) @(BackendClusterArg2 (JustAccumulator op) _ _) $ outToSh $ coerce x
shToOut x = coerce @(BackendClusterArg2 op _ _) @(BackendClusterArg2 (JustAccumulator op) _ _) $ shToOut $ coerce x
Expand All @@ -469,7 +488,7 @@ deriving instance (Eq (BackendClusterArg2 op x y)) => Eq (BackendClusterArg2 (Ju

toOnlyAcc :: Cluster op args -> Cluster (JustAccumulator op) args
toOnlyAcc (Fused f l r) = Fused f (toOnlyAcc l) (toOnlyAcc r)
toOnlyAcc (Op (SLVOp (SOp (SOAOp op soa) sort) sa)) = Op (SLVOp (SOp (SOAOp (JA op) soa) sort) sa)
toOnlyAcc (Op (SOp (SOAOp op soa) sort) l) = Op (SOp (SOAOp (JA op) soa) sort) l

pattern CJ :: f a -> Compose Maybe f a
pattern CJ x = Compose (Just x)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ compile uid module' = do
withModuleFromAST ctx ast $ \mdl ->
withNativeTargetMachine $ \machine ->
withTargetLibraryInfo triple $ \libinfo -> do
-- hPutStrLn stderr . T.unpack . decodeUtf8 =<< moduleLLVMAssembly mdl
hPutStrLn stderr . T.unpack . decodeUtf8 =<< moduleLLVMAssembly mdl

optimiseModule datalayout (Just machine) (Just libinfo) mdl

-- putStrLn . T.unpack . decodeUtf8 =<< moduleLLVMAssembly mdl
Debug.when Debug.verbose $ do
Debug.traceM Debug.dump_cc stext . decodeUtf8 =<< moduleLLVMAssembly mdl
Debug.traceM Debug.dump_asm stext . decodeUtf8 =<< moduleTargetAssembly machine mdl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ bindAwhileIO :: InputOutputR input output -> IO (Values output, Values input)
bindAwhileIO InputOutputRsignal = do
signal <- newSignal
return (ValuesSingle $ Value signal, ValuesSingle $ Value signal)
bindAwhileIO InputOutputRref = do
bindAwhileIO (InputOutputRref _) = do
ioref <- newIORef $ internalError "Illegal schedule: Read from ref without value. Some synchronization might be missing."
return (ValuesSingle $ Value $ OutputRef ioref, ValuesSingle $ Value $ Ref ioref)
bindAwhileIO (InputOutputRpair io1 io2) = do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ instance MakesILP NativeOp where
( inputConstraints l lIns
<> ILP.c (InDir l) .==. int i
<> ILP.c (InDims l) .==. ILP.c (OutDims l)
<> rankifmanifest shrO l
<> inrankifmanifest shrO l
-- .+. timesN (int 3 .+. c (OutDir l))
-- When we switch to gather, like in the paper, we need to add this term.
-- 4 + dir is always positive, and this is exactly why we (elsewhere) define `n` as `5+(size nodes)`
Expand All @@ -226,15 +226,15 @@ instance MakesILP NativeOp where
mkGraph NGenerate (_ :>: L (ArgArray Out (ArrayR shr _) _ _) _ :>: ArgsNil) l =
Graph.Info
mempty
(rankifmanifest shr l)
(outrankifmanifest shr l)
(defaultBounds l)
mkGraph NMap (_ :>: L (ArgArray In (ArrayR shr _) _ _) (_, lIns) :>: _ :>: ArgsNil) l =
Graph.Info
mempty
( inputConstraints l lIns
<> ILP.c (InDir l) .==. ILP.c (OutDir l)
<> ILP.c (InDims l) .==. ILP.c (OutDims l)
<> rankifmanifest shr l)
<> inrankifmanifest shr l)
(defaultBounds l)
mkGraph NPermute (_ :>: L _ (_, lTargets) :>: L _ (_, lLocks) :>: _ :>: L (ArgArray In (ArrayR shr _) _ _) (_, lIns) :>: ArgsNil) l =
Graph.Info
Expand Down Expand Up @@ -268,7 +268,7 @@ instance MakesILP NativeOp where
( inputConstraints l lIns
<> ILP.c (InDir l) .==. ILP.c (OutDir l)
<> ILP.c (InDims l) .==. int 1 .+. ILP.c (OutDims l)
<> rankifmanifest (ShapeRsnoc shr) l)
<> inrankifmanifest (ShapeRsnoc shr) l)
(defaultBounds l)

labelLabelledArg :: M.Map (Graph.Var NativeOp) Int -> Label -> LabelledArg env a -> LabelledArgOp NativeOp env a
Expand All @@ -289,9 +289,13 @@ inputConstraints l = foldMap $ \lIn ->
<> timesN (fused lIn l) .>=. ILP.c (InDims l) .-. ILP.c (OutDims lIn)
<> (-1) .*. timesN (fused lIn l) .<=. ILP.c (InDims l) .-. ILP.c (OutDims lIn)

rankifmanifest :: ShapeR sh -> Label -> Constraint NativeOp
rankifmanifest shr l = ILP.int (rank shr) .+. timesN (manifest l) .>=. ILP.c (InDims l)
<> ILP.int (rank shr) .-. timesN (manifest l) .<=. ILP.c (InDims l)
inrankifmanifest :: ShapeR sh -> Label -> Constraint NativeOp
inrankifmanifest shr l = ILP.int (rank shr) .+. timesN (manifest l) .>=. ILP.c (InDims l)
<> ILP.int (rank shr) .-. timesN (manifest l) .<=. ILP.c (InDims l)

outrankifmanifest :: ShapeR sh -> Label -> Constraint NativeOp
outrankifmanifest shr l = ILP.int (rank shr) .+. timesN (manifest l) .>=. ILP.c (OutDims l)
<> ILP.int (rank shr) .-. timesN (manifest l) .<=. ILP.c (OutDims l)



Expand All @@ -309,6 +313,8 @@ instance ShrinkArg (BackendClusterArg NativeOp) where
data IndexPermutation env where
BP :: ShapeR sh1 -> ShapeR sh2 -> Fun env (sh1 -> sh2) -> GroundVars env sh1 -> IndexPermutation env
type Depth = Int
instance Show (BackendClusterArg2 NativeOp env arg) where
show (BCAN2 _ d) = "depth " <> show d
instance StaticClusterAnalysis NativeOp where
data BackendClusterArg2 NativeOp env arg where
BCAN2 :: Maybe (IndexPermutation env) -> Depth -> BackendClusterArg2 NativeOp env arg
Expand All @@ -334,7 +340,9 @@ instance StaticClusterAnalysis NativeOp where
| otherwise = error "BP shapeR doesn't match backpermute output shape"
onOp NBackpermute (BCAN2 Nothing d :>: ArgsNil) (ArgFun f :>: ArgArray In (ArrayR shrI _) _ _ :>: ArgArray Out (ArrayR shrO _) sh _ :>: ArgsNil) _
= BCAN2 Nothing d :>: BCAN2 (Just (BP shrO shrI f sh)) d :>: BCAN2 Nothing d :>: ArgsNil
onOp NGenerate (bp :>: ArgsNil) _ _ = bcan2id bp :>: bp :>: ArgsNil -- storing the bp in the function argument. Probably not required, could just take it from the array one during codegen
onOp NGenerate (bp :>: ArgsNil) (_:>:ArgArray Out (ArrayR shR _) _ _ :>:ArgsNil) _ =
Debug.Trace.traceShow (bp, rank shR) $
bcan2id bp :>: bp :>: ArgsNil -- storing the bp in the function argument. Probably not required, could just take it from the array one during codegen
onOp NPermute ArgsNil (_:>:_:>:_:>:_:>:ArgArray In (ArrayR shR _) _ _ :>:ArgsNil) _ =
BCAN2 Nothing 0 :>: BCAN2 Nothing 0 :>: BCAN2 Nothing 0 :>: BCAN2 Nothing 0 :>: BCAN2 Nothing (rank shR) :>: ArgsNil
onOp NFold2 (bp :>: ArgsNil) (_ :>: ArgArray In _ fs _ :>: _ :>: ArgsNil) _ = BCAN2 Nothing 0 :>: fold2bp bp (case fs of TupRpair _ x -> x) :>: bp :>: ArgsNil
Expand Down
53 changes: 38 additions & 15 deletions accelerate-llvm-native/test/nofib/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,52 @@ import Data.Array.Accelerate.LLVM.Native
import Data.Array.Accelerate.LLVM.Native.Operation
import Criterion.Main
import Control.Monad
import Prelude (Show(..), IO, )
import Prelude (Show(..), IO, print, putStrLn)
import qualified Prelude as Prelude
import Data.Array.Accelerate.Trafo.Partitioning.ILP.Solve
import Data.Array.Accelerate.Data.Bits
import Data.Array.Accelerate.Unsafe

main :: IO ()
main = do
Prelude.print $ runN @Interpreter complex $ fromList (Z:.100) $ Prelude.map (`Prelude.mod` 50) [1 :: Int ..]
-- benchmarking:
-- defaultMain $
-- Prelude.map (benchOption . Prelude.Left) [minBound :: Objective .. maxBound]
-- Prelude.++
-- Prelude.map (benchOption . Prelude.Right) [NoFusion, GreedyFusion]

let xs = fromList (Z :. 10) [1 :: Int ..]
let ys = use xs
putStrLn "generate:"
let f = generate (I1 10) (\(I1 x0) -> 10 :: Exp Int)
-- putStrLn $ test @UniformScheduleFun @NativeKernel f
print $ run @Native f

putStrLn "mapmap:"
let f = map (+1) . map (*2) -- $ ys
-- putStrLn $ test @UniformScheduleFun @NativeKernel f
-- putStrLn $ test @UniformScheduleFun @NativeKernel (f ys)
print $ runN @Native f xs
print $ runN @Native (f ys)

putStrLn "fold:"
let f = fold1 (+) ys
-- putStrLn $ test @UniformScheduleFun @NativeKernel f
print $ run @Native f

putStrLn "scan:"
let f = scanl1 (+) ys
-- putStrLn $ test @UniformScheduleFun @NativeKernel f
print $ run @Native f

-- Prelude.print $ runNWithObj @Native ArrayReadsWrites $ quicksort $ use $ fromList (Z :. 5) [100::Int, 200, 3, 5, 4]
where

----------------------------BENCHMARKS------------------------------
-- complex from the ILP example
-- complexAdd a variation on complex, where the results are zipWith-ed together
-- singleLoop from the introduction
-- diagonal two maps, fused diagonally
--------------------------------------------------------------------

benchmarkmain = defaultMain $
Prelude.map (benchOption . Prelude.Left) [minBound :: Objective .. maxBound]
Prelude.++
Prelude.map (benchOption . Prelude.Right) [NoFusion, GreedyFusion]
where
benchOption :: Prelude.Either Objective Benchmarking -> Benchmark
benchOption obj = bgroup (show obj)
[
Expand Down Expand Up @@ -72,12 +101,6 @@ main = do
-- , bench "diagonal' " $ nf (flip linearIndexArray 0 . Prelude.fst . p) xs)
-- ]

----------------------------BENCHMARKS------------------------------
-- complex from the ILP example
-- complexAdd a variation on complex, where the results are zipWith-ed together
-- singleLoop from the introduction
-- diagonal two maps, fused diagonally
--------------------------------------------------------------------

complex :: Acc (Vector Int) -> Acc (Vector Int, Vector Int)
complex xs =
Expand Down
14 changes: 7 additions & 7 deletions stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# For advanced use and comprehensive documentation of the format, please see:
# https://docs.haskellstack.org/en/stable/yaml_configuration/

resolver: lts-21.12
resolver: lts-21.7

packages:
- accelerate-llvm
Expand All @@ -15,11 +15,11 @@ extra-deps:
- OptDir-0.0.4
- bytestring-encoding-0.1.2.0
- ../accelerate
- MIP-0.1.1.0
# - github: msakai/haskell-MIP
# commit: 4295aa21a24a30926b55770c55ac00f749fb8a39
# subdirs:
# - MIP
# - MIP-0.1.1.0
- github: msakai/haskell-MIP
commit: 4295aa21a24a30926b55770c55ac00f749fb8a39
subdirs:
- MIP

- github: llvm-hs/llvm-hs
commit: e4b3cfa47e72f094ab109884f18acfc666b0fb7d # llvm-15
Expand All @@ -29,7 +29,7 @@ extra-deps:
- llvm-hs-pure

# Override default flag values for local packages and extra-deps
# flags: {}
# flags:

# Extra per-package and global ghc options
# ghc-options:
Expand Down

0 comments on commit 263f8a3

Please sign in to comment.