    {-# LANGUAGE TypeFamilies #-}

    -- | A representation for multicore CPU parallelism.
    module Futhark.IR.MC
      ( MC,

        -- * Simplification
        simplifyProg,

        -- * Module re-exports
        module Futhark.IR.Prop,
        module Futhark.IR.Traversals,
        module Futhark.IR.Pretty,
        module Futhark.IR.Syntax,
        module Futhark.IR.SegOp,
        module Futhark.IR.SOACS.SOAC,
        module Futhark.IR.MC.Op,
      )
    where

    import Futhark.Builder
    import Futhark.Construct
    import Futhark.IR.MC.Op
    import Futhark.IR.Pretty
    import Futhark.IR.Prop
    import Futhark.IR.SOACS.SOAC hiding (HistOp (..))
    import Futhark.IR.SOACS.Simplify qualified as SOAC
    import Futhark.IR.SegOp
    import Futhark.IR.Syntax
    import Futhark.IR.Traversals
    import Futhark.IR.TypeCheck qualified as TypeCheck
    import Futhark.Optimise.Simplify qualified as Simplify
    import Futhark.Optimise.Simplify.Engine qualified as Engine
    import Futhark.Optimise.Simplify.Rules
    import Futhark.Pass

    data MC

    instance RepTypes MC where
      type OpC MC = MCOp SOAC

    instance ASTRep MC where
      expTypesFromPat :: forall (m :: * -> *).
    (HasScope MC m, Monad m) =>
    Pat (LetDec MC) -> m [BranchType MC]
    expTypesFromPat = [ExtType] -> m [ExtType]
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([ExtType] -> m [ExtType])
    -> (Pat Type -> [ExtType]) -> Pat Type -> m [ExtType]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Pat Type -> [ExtType]
    forall dec. Typed dec => Pat dec -> [ExtType]
    expExtTypesFromPat

    instance TypeCheck.Checkable MC where
      checkOp :: Op (Aliases MC) -> TypeM MC ()
    checkOp = (SOAC (Aliases MC) -> TypeM MC ())
    -> MCOp SOAC (Aliases MC) -> TypeM MC ()
    forall rep (op :: * -> *).
    Checkable rep =>
    (op (Aliases rep) -> TypeM rep ())
    -> MCOp op (Aliases rep) -> TypeM rep ()
    typeCheckMCOp SOAC (Aliases MC) -> TypeM MC ()
    forall rep. Checkable rep => SOAC (Aliases rep) -> TypeM rep ()
    typeCheckSOAC

    instance Buildable MC where
      mkBody :: Stms MC -> Result -> Body MC
    mkBody = BodyDec MC -> Stms MC -> Result -> Body MC
    forall rep. BodyDec rep -> Stms rep -> Result -> Body rep
    Body ()
      mkExpPat :: [Ident] -> Exp MC -> Pat (LetDec MC)
    mkExpPat [Ident]
    idents Exp MC
    _ = [Ident] -> Pat Type
    basicPat [Ident]
    idents
      mkExpDec :: Pat (LetDec MC) -> Exp MC -> ExpDec MC
    mkExpDec Pat (LetDec MC)
    _ Exp MC
    _ = ()
      mkLetNames :: forall (m :: * -> *).
    (MonadFreshNames m, HasScope MC m) =>
    [VName] -> Exp MC -> m (Stm MC)
    mkLetNames = [VName] -> Exp MC -> m (Stm MC)
    forall rep (m :: * -> *).
    (ExpDec rep ~ (), LetDec rep ~ Type, MonadFreshNames m,
     TypedOp (OpC rep), HasScope rep m) =>
    [VName] -> Exp rep -> m (Stm rep)
    simpleMkLetNames

    instance BuilderOps MC

    instance BuilderOps (Engine.Wise MC)

    instance PrettyRep MC

    instance TraverseOpStms (Engine.Wise MC) where
      traverseOpStms :: forall (m :: * -> *).
    Monad m =>
    OpStmsTraverser m (Op (Wise MC)) (Wise MC)
    traverseOpStms = OpStmsTraverser m (SOAC (Wise MC)) (Wise MC)
    -> OpStmsTraverser m (MCOp SOAC (Wise MC)) (Wise MC)
    forall (m :: * -> *) (op :: * -> *) rep.
    Monad m =>
    OpStmsTraverser m (op rep) rep
    -> OpStmsTraverser m (MCOp op rep) rep
    traverseMCOpStms OpStmsTraverser m (SOAC (Wise MC)) (Wise MC)
    forall (m :: * -> *) rep.
    Monad m =>
    OpStmsTraverser m (SOAC rep) rep
    traverseSOACStms

    simpleMC :: Simplify.SimpleOps MC
    simpleMC :: SimpleOps MC
    simpleMC = SimplifyOp MC (Op (Wise MC)) -> SimpleOps MC
    forall rep.
    (SimplifiableRep rep, Buildable rep) =>
    SimplifyOp rep (Op (Wise rep)) -> SimpleOps rep
    Simplify.bindableSimpleOps (SimplifyOp MC (Op (Wise MC)) -> SimpleOps MC)
    -> SimplifyOp MC (Op (Wise MC)) -> SimpleOps MC
    forall a b. (a -> b) -> a -> b
    $ SimplifyOp MC (SOAC (Wise MC))
    -> MCOp SOAC (Wise MC)
    -> SimpleM MC (MCOp SOAC (Wise MC), Stms (Wise MC))
    forall rep (op :: * -> *).
    (SimplifiableRep rep, BodyDec rep ~ ()) =>
    SimplifyOp rep (op (Wise rep))
    -> MCOp op (Wise rep)
    -> SimpleM rep (MCOp op (Wise rep), Stms (Wise rep))
    simplifyMCOp SimplifyOp MC (SOAC (Wise MC))
    forall rep. SimplifiableRep rep => SimplifyOp rep (SOAC (Wise rep))
    SOAC.simplifySOAC

    simplifyProg :: Prog MC -> PassM (Prog MC)
    simplifyProg :: Prog MC -> PassM (Prog MC)
    simplifyProg = SimpleOps MC
    -> RuleBook (Wise MC)
    -> HoistBlockers MC
    -> Prog MC
    -> PassM (Prog MC)
    forall rep.
    SimplifiableRep rep =>
    SimpleOps rep
    -> RuleBook (Wise rep)
    -> HoistBlockers rep
    -> Prog rep
    -> PassM (Prog rep)
    Simplify.simplifyProg SimpleOps MC
    simpleMC RuleBook (Wise MC)
    rules HoistBlockers MC
    forall {k} {rep :: k}. HoistBlockers rep
    blockers
      where
        blockers :: HoistBlockers rep
    blockers = HoistBlockers rep
    forall {k} {rep :: k}. HoistBlockers rep
    Engine.noExtraHoistBlockers
        rules :: RuleBook (Wise MC)
    rules = RuleBook (Wise MC)
    forall rep. (BuilderOps rep, TraverseOpStms rep) => RuleBook rep
    standardRules RuleBook (Wise MC) -> RuleBook (Wise MC) -> RuleBook (Wise MC)
    forall a. Semigroup a => a -> a -> a
    <> RuleBook (Wise MC)
    forall rep.
    (HasSegOp rep, BuilderOps rep, Buildable rep, Aliased rep) =>
    RuleBook rep
    segOpRules

    instance HasSegOp MC where
      type SegOpLevel MC = ()
      asSegOp :: Op MC -> Maybe (SegOp (SegOpLevel MC) MC)
    asSegOp = Maybe (SegOp () MC) -> MCOp SOAC MC -> Maybe (SegOp () MC)
    forall a b. a -> b -> a
    const Maybe (SegOp () MC)
    forall a. Maybe a
    Nothing
      segOp :: SegOp (SegOpLevel MC) MC -> Op MC
    segOp = Maybe (SegOp () MC) -> SegOp () MC -> MCOp SOAC MC
    forall (op :: * -> *) rep.
    Maybe (SegOp () rep) -> SegOp () rep -> MCOp op rep
    ParOp Maybe (SegOp () MC)
    forall a. Maybe a
    Nothing

    instance HasSegOp (Engine.Wise MC) where
      type SegOpLevel (Engine.Wise MC) = ()
      asSegOp :: Op (Wise MC) -> Maybe (SegOp (SegOpLevel (Wise MC)) (Wise MC))
    asSegOp = Maybe (SegOp () (Wise MC))
    -> MCOp SOAC (Wise MC) -> Maybe (SegOp () (Wise MC))
    forall a b. a -> b -> a
    const Maybe (SegOp () (Wise MC))
    forall a. Maybe a
    Nothing
      segOp :: SegOp (SegOpLevel (Wise MC)) (Wise MC) -> Op (Wise MC)
    segOp = Maybe (SegOp () (Wise MC))
    -> SegOp () (Wise MC) -> MCOp SOAC (Wise MC)
    forall (op :: * -> *) rep.
    Maybe (SegOp () rep) -> SegOp () rep -> MCOp op rep
    ParOp Maybe (SegOp () (Wise MC))
    forall a. Maybe a
    Nothing