packages feed

apple-0.3.0.0: src/Asm/Aarch64/CF.hs

module Asm.Aarch64.CF ( mkControlFlow
                      , expand
                      , udd
                      ) where

import           Asm.Aarch64
import           Asm.BB
import           Asm.CF
import           Asm.M
import           CF
import           Class.E      as E
import           Data.Functor (void, ($>))
import qualified Data.IntSet  as IS

mkControlFlow :: (E reg, E freg, E f2reg) => [BB AArch64 reg freg f2reg () ()] -> [BB AArch64 reg freg f2reg () ControlAnn]
mkControlFlow instrs = runFreshM (broadcasts instrs *> addControlFlow instrs)

expand :: (E reg, E freg, E f2reg) => BB AArch64 reg freg f2reg () Liveness -> [AArch64 reg freg f2reg Liveness]
expand (BB asms@(_:_) li) = scanr (\n p -> lN n (ann p)) lS iasms
    where lN a s =
            let ai=uses a <> (ao IS.\\ defs a)
                ao=ins s
                aif=usesF a <> (aof IS.\\ defsF a)
                aof=fins s
            in a $> Liveness ai ao aif aof
          lS = let ao=out li
                   aof=fout li
               in asm $> Liveness (uses asm `IS.union` (ao `IS.difference` defs asm)) ao (usesF asm `IS.union` (aof `IS.difference` defsF asm)) aof
          (iasms, asm) = (init asms, last asms)
expand _ = []

addControlFlow :: (E reg, E freg, E f2reg) => [BB AArch64 reg freg f2reg () ()] -> FreshM [BB AArch64 reg freg f2reg () ControlAnn]
addControlFlow [] = pure []
addControlFlow (BB [] _:bbs) = addControlFlow bbs
addControlFlow (BB asms _:bbs) = do
    { i <- case asms of
        (Label _ l:_) -> lookupLabel l
        _             -> getFresh
    ; (f, bbs') <- next bbs
    ; acc <- case last asms of
            B _ lϵ        -> do {l_i <- lookupLabel lϵ; pure [l_i]}
            Bc _ _ lϵ     -> do {l_i <- lookupLabel lϵ; pure (f [l_i])}
            Tbnz _ _ _ lϵ -> do {l_i <- lookupLabel lϵ; pure $ f [l_i]}
            Tbz _ _ _ lϵ  -> do {l_i <- lookupLabel lϵ; pure $ f [l_i]}
            Cbnz _ _ lϵ   -> do {l_i <- lookupLabel lϵ; pure $ f [l_i]}
            C _ lϵ        -> do {l_i <- lookupLabel lϵ; pure $ f [l_i]}
            RetL _ lϵ     -> lC lϵ
            _             -> pure (f [])
    ; pure (BB asms (ControlAnn i acc (udb asms)) : bbs')
    }

uA :: E reg => Addr reg -> IS.IntSet
uA (R r)      = singleton r
uA (RP r _)   = singleton r
uA (BI b i _) = fromList [b, i]

udb asms = UD (uBB asms) (uBBF asms) (dBB asms) (dBBF asms)
udd asm = UD (uses asm) (usesF asm) (defs asm) (defsF asm)

uBB, dBB :: E reg => [AArch64 reg freg f2reg a] -> IS.IntSet
uBB = foldr (\p n -> uses p `IS.union` (n IS.\\ defs p)) IS.empty
dBB = foldMap defs

uBBF, dBBF :: (E freg, E f2reg) => [AArch64 reg freg f2reg a] -> IS.IntSet
uBBF = foldr (\p n -> usesF p `IS.union` (n IS.\\ defsF p)) IS.empty
dBBF = foldMap defsF

defs, uses :: E reg => AArch64 reg freg f2reg a -> IS.IntSet
uses (MovRR _ _ r)        = singleton r
uses MovRC{}              = IS.empty
uses FMovXX{}             = IS.empty
uses (Ldr _ _ a)          = uA a
uses (LdrB _ _ a)         = uA a
uses (Str _ r a)          = IS.insert (E.toInt r) $ uA a
uses (StrB _ r a)         = IS.insert (E.toInt r) $ uA a
uses (Ldp _ _ _ a)        = uA a
uses (Stp _ r0 r1 a)      = fromList [r0, r1] <> uA a
uses (LdrD _ _ a)         = uA a
uses (SubRR _ _ r0 r1)    = fromList [r0, r1]
uses (AddRR _ _ r0 r1)    = fromList [r0, r1]
uses (AddRRS _ _ r0 r1 _) = fromList [r0, r1]
uses (AndRR _ _ r0 r1)    = fromList [r0, r1]
uses (OrRR _ _ r0 r1)     = fromList [r0, r1]
uses (Eor _ _ r0 r1)      = fromList [r0, r1]
uses (EorI _ _ r0 _)      = singleton r0
uses ZeroR{}              = IS.empty
uses (Mvn _ _ r)          = singleton r
uses (AddRC _ _ r _)      = singleton r
uses (SubRC _ _ r _)      = singleton r
uses (Lsl _ _ r _)        = singleton r
uses (Asr _ _ r _)        = singleton r
uses (CmpRR _ r0 r1)      = fromList [r0, r1]
uses (CmpRC _ r _)        = singleton r
uses (Neg _ _ r)          = singleton r
uses Fmul{}               = IS.empty
uses Fadd{}               = IS.empty
uses Fsub{}               = IS.empty
uses FcmpZ{}              = IS.empty
uses (StrD _ _ a)         = uA a
uses (MulRR _ _ r0 r1)    = fromList [r0, r1]
uses (Madd _ _ r0 r1 r2)  = fromList [r0, r1, r2]
uses (Msub _ _ r0 r1 r2)  = fromList [r0, r1, r2]
uses (Sdiv _ _ r0 r1)     = fromList [r0, r1]
uses Fdiv{}               = IS.empty
uses (Scvtf _ _ r)        = singleton r
uses Fcvtms{}             = IS.empty
uses Fcvtas{}             = IS.empty
uses (FMovDR _ _ r)       = singleton r
uses (MovK _ r _ _)       = singleton r
uses MovZ{}               = IS.empty
uses Fcmp{}               = IS.empty
uses (StpD _ _ _ a)       = uA a
uses (Stp2 _ _ _ a)       = uA a
uses (LdpD _ _ _ a)       = uA a
uses (Ldp2 _ _ _ a)       = uA a
uses Fmadd{}              = IS.empty
uses Fmsub{}              = IS.empty
uses Fsqrt{}              = IS.empty
uses Fneg{}               = IS.empty
uses Frintm{}             = IS.empty
uses MrsR{}               = IS.empty
uses (MovRCf _ _ Free)    = singleton CArg0
uses (MovRCf _ _ Malloc)  = singleton CArg0
uses MovRCf{}             = IS.empty
uses LdrRL{}              = IS.empty
uses (Blr _ r)            = singleton r
uses Fmax{}               = IS.empty
uses Fmin{}               = IS.empty
uses Fabs{}               = IS.empty
uses (Csel _ _ r1 r2 _)   = fromList [r1, r2]
uses Fcsel{}              = IS.empty
uses (TstI _ r _)         = singleton r
uses Label{}              = IS.empty
uses Bc{}                 = IS.empty
uses B{}                  = IS.empty
uses (Cbnz _ r _)         = singleton r
uses (Cbz _ r _)          = singleton r
uses (Tbnz _ r _ _)       = singleton r
uses (Tbz _ r _ _)        = singleton r
uses Ret{}                = singleton CArg0
uses Cset{}               = IS.empty
uses Bl{}                 = IS.empty
uses C{}                  = singleton ASP
uses RetL{}               = singleton LR

defs FMovXX{}            = IS.empty
defs (MovRC _ r _)       = singleton r
defs (MovRR _ r _)       = singleton r
defs (Ldr _ r _)         = singleton r
defs (LdrB _ r _)        = singleton r
defs Str{}               = IS.empty
defs StrB{}              = IS.empty
defs LdrD{}              = IS.empty
defs LdpD{}              = IS.empty
defs Stp{}               = IS.empty
defs StpD{}              = IS.empty
defs Stp2{}              = IS.empty
defs Ldp2{}              = IS.empty
defs (Ldp _ r0 r1 _)     = fromList [r0, r1]
defs (SubRR _ r _ _)     = singleton r
defs (AddRR _ r _ _)     = singleton r
defs (AddRRS _ r _ _ _)  = singleton r
defs (AndRR _ r _ _)     = singleton r
defs (OrRR _ r _ _)      = singleton r
defs (Eor _ r _ _)       = singleton r
defs (EorI _ r _ _)      = singleton r
defs (ZeroR _ r)         = singleton r
defs (Mvn _ r _)         = singleton r
defs (AddRC _ r _ _)     = singleton r
defs (SubRC _ r _ _)     = singleton r
defs (Lsl _ r _ _)       = singleton r
defs (Asr _ r _ _)       = singleton r
defs CmpRC{}             = IS.empty
defs CmpRR{}             = IS.empty
defs (Neg _ r _)         = singleton r
defs Fmul{}              = IS.empty
defs Fadd{}              = IS.empty
defs Fsub{}              = IS.empty
defs FcmpZ{}             = IS.empty
defs StrD{}              = IS.empty
defs (MulRR _ r _ _)     = singleton r
defs (Madd _ r _ _ _)    = singleton r
defs (Msub _ r _ _ _)    = singleton r
defs (Sdiv _ r _ _)      = singleton r
defs Fdiv{}              = IS.empty
defs Scvtf{}             = IS.empty
defs (Fcvtms _ r _)      = singleton r
defs (Fcvtas _ r _)      = singleton r
defs FMovDR{}            = IS.empty
defs (MovK _ r _ _)      = singleton r
defs (MovZ _ r _ _)      = singleton r
defs Fcmp{}              = IS.empty
defs Fmadd{}             = IS.empty
defs Fmsub{}             = IS.empty
defs Fsqrt{}             = IS.empty
defs Fneg{}              = IS.empty
defs Frintm{}            = IS.empty
defs (MrsR _ r)          = singleton r
defs Blr{}               = singleton LR
defs (MovRCf _ r Malloc) = singleton r <> singleton CArg0
defs (LdrRL _ r _)       = singleton r
defs MovRCf{}            = IS.empty
defs Fmax{}              = IS.empty
defs Fmin{}              = IS.empty
defs Fabs{}              = IS.empty
defs (Csel _ r _ _ _)    = singleton r
defs Fcsel{}             = IS.empty
defs TstI{}              = IS.empty
defs Label{}             = IS.empty
defs Bc{}                = IS.empty
defs B{}                 = IS.empty
defs Cbnz{}              = IS.empty
defs Cbz{}               = IS.empty
defs Tbnz{}              = IS.empty
defs Tbz{}               = IS.empty
defs Ret{}               = IS.empty
defs (Cset _ r _)        = singleton r
defs Bl{}                = singleton LR
defs C{}                 = fromList [LR, FP]
defs RetL{}              = IS.empty

defsF, usesF :: (E freg, E f2reg) => AArch64 reg freg f2reg ann -> IS.IntSet
defsF (FMovXX _ r _)     = singleton r
defsF MovRR{}            = IS.empty
defsF MovRC{}            = IS.empty
defsF Ldr{}              = IS.empty
defsF LdrB{}             = IS.empty
defsF Str{}              = IS.empty
defsF StrB{}             = IS.empty
defsF (LdrD _ r _)       = singleton r
defsF (Ldp2 _ q0 q1 _)   = fromList [q0, q1]
defsF AddRR{}            = IS.empty
defsF AddRRS{}           = IS.empty
defsF SubRR{}            = IS.empty
defsF AndRR{}            = IS.empty
defsF OrRR{}             = IS.empty
defsF Eor{}              = IS.empty
defsF EorI{}             = IS.empty
defsF ZeroR{}            = IS.empty
defsF Mvn{}              = IS.empty
defsF AddRC{}            = IS.empty
defsF SubRC{}            = IS.empty
defsF Lsl{}              = IS.empty
defsF Asr{}              = IS.empty
defsF CmpRR{}            = IS.empty
defsF CmpRC{}            = IS.empty
defsF Neg{}              = IS.empty
defsF (Fmul _ r _ _)     = singleton r
defsF (Fadd _ r _ _)     = singleton r
defsF (Fsub _ r _ _)     = singleton r
defsF FcmpZ{}            = IS.empty
defsF (Fdiv _ d _ _)     = singleton d
defsF StrD{}             = IS.empty
defsF MulRR{}            = IS.empty
defsF Madd{}             = IS.empty
defsF Msub{}             = IS.empty
defsF Sdiv{}             = IS.empty
defsF (Scvtf _ r _)      = singleton r
defsF Fcvtms{}           = IS.empty
defsF Fcvtas{}           = IS.empty
defsF (FMovDR _ r _)     = singleton r
defsF MovK{}             = IS.empty
defsF MovZ{}             = IS.empty
defsF Fcmp{}             = IS.empty
defsF (LdpD _ r0 r1 _)   = fromList [r0, r1]
defsF Ldp{}              = IS.empty
defsF Stp{}              = IS.empty
defsF StpD{}             = IS.empty
defsF Stp2{}             = IS.empty
defsF (Fmadd _ d0 _ _ _) = singleton d0
defsF (Fmsub _ d0 _ _ _) = singleton d0
defsF (Fsqrt _ d _)      = singleton d
defsF (Fneg _ d _)       = singleton d
defsF (Frintm _ d _)     = singleton d
defsF MrsR{}             = IS.empty
defsF Blr{}              = IS.empty
defsF (MovRCf _ _ Exp)   = singleton FArg0
defsF (MovRCf _ _ Log)   = singleton FArg0
defsF (MovRCf _ _ Pow)   = singleton FArg0
defsF MovRCf{}           = IS.empty
defsF LdrRL{}            = IS.empty
defsF (Fmax _ d _ _)     = singleton d
defsF (Fmin _ d _ _)     = singleton d
defsF (Fabs _ d _)       = singleton d
defsF Csel{}             = IS.empty
defsF TstI{}             = IS.empty
defsF (Fcsel _ d0 _ _ _) = singleton d0
defsF Label{}            = IS.empty
defsF Bc{}               = IS.empty
defsF B{}                = IS.empty
defsF Cbnz{}             = IS.empty
defsF Cbz{}              = IS.empty
defsF Tbnz{}             = IS.empty
defsF Tbz{}              = IS.empty
defsF Ret{}              = IS.empty
defsF RetL{}             = IS.empty
defsF Cset{}             = IS.empty
defsF Bl{}               = IS.empty
defsF C{}                = IS.empty

usesF (FMovXX _ _ r)       = singleton r
usesF MovRR{}              = IS.empty
usesF MovRC{}              = IS.empty
usesF Ldr{}                = IS.empty
usesF LdrB{}               = IS.empty
usesF LdrD{}               = IS.empty
usesF Str{}                = IS.empty
usesF StrB{}               = IS.empty
usesF AddRR{}              = IS.empty
usesF AddRRS{}             = IS.empty
usesF SubRR{}              = IS.empty
usesF ZeroR{}              = IS.empty
usesF Mvn{}                = IS.empty
usesF AndRR{}              = IS.empty
usesF OrRR{}               = IS.empty
usesF Eor{}                = IS.empty
usesF EorI{}               = IS.empty
usesF AddRC{}              = IS.empty
usesF SubRC{}              = IS.empty
usesF Lsl{}                = IS.empty
usesF Asr{}                = IS.empty
usesF CmpRR{}              = IS.empty
usesF CmpRC{}              = IS.empty
usesF Neg{}                = IS.empty
usesF (Fadd _ _ r0 r1)     = fromList [r0, r1]
usesF (Fsub _ _ r0 r1)     = fromList [r0, r1]
usesF (Fmul _ _ r0 r1)     = fromList [r0, r1]
usesF (FcmpZ _ r)          = singleton r
usesF (Fdiv _ _ r0 r1)     = fromList [r0, r1]
usesF (StrD _ r _)         = singleton r
usesF MulRR{}              = IS.empty
usesF Madd{}               = IS.empty
usesF Msub{}               = IS.empty
usesF Sdiv{}               = IS.empty
usesF Scvtf{}              = IS.empty
usesF (Fcvtms _ _ r)       = singleton r
usesF (Fcvtas _ _ r)       = singleton r
usesF MovK{}               = IS.empty
usesF MovZ{}               = IS.empty
usesF FMovDR{}             = IS.empty
usesF (Fcmp _ r0 r1)       = fromList [r0, r1]
usesF (StpD _ r0 r1 _)     = fromList [r0, r1]
usesF (Stp2 _ q0 q1 _)     = fromList [q0, q1]
usesF Ldp2{}               = IS.empty
usesF Stp{}                = IS.empty
usesF Ldp{}                = IS.empty
usesF LdpD{}               = IS.empty
usesF (Fmadd _ _ d0 d1 d2) = fromList [d0, d1, d2]
usesF (Fmsub _ _ d0 d1 d2) = fromList [d0, d1, d2]
usesF (Fsqrt _ _ d)        = singleton d
usesF (Fneg _ _ d)         = singleton d
usesF (Frintm _ _ d)       = singleton d
usesF MrsR{}               = IS.empty
usesF Blr{}                = IS.empty
usesF (MovRCf _ _ Exp)     = singleton FArg0
usesF (MovRCf _ _ Log)     = singleton FArg0
usesF (MovRCf _ _ Pow)     = fromList [FArg0, FArg1]
usesF MovRCf{}             = IS.empty
usesF LdrRL{}              = IS.empty
usesF (Fmax _ _ d0 d1)     = fromList [d0, d1]
usesF (Fmin _ _ d0 d1)     = fromList [d0, d1]
usesF (Fabs _ _ d)         = singleton d
usesF Csel{}               = IS.empty
usesF TstI{}               = IS.empty
usesF (Fcsel _ _ d0 d1 _)  = fromList [d0, d1]
usesF Label{}              = IS.empty
usesF Bc{}                 = IS.empty
usesF B{}                  = IS.empty
usesF Cbnz{}               = IS.empty
usesF Cbz{}                = IS.empty
usesF Tbnz{}               = IS.empty
usesF Tbz{}                = IS.empty
usesF Ret{}                = fromList [FArg0, FArg1]
usesF Cset{}               = IS.empty
usesF Bl{}                 = IS.empty
usesF C{}                  = IS.empty
usesF RetL{}               = IS.empty

next :: (E reg, E freg, E f2reg) => [BB AArch64 reg freg f2reg () ()] -> FreshM ([N] -> [N], [BB AArch64 reg freg f2reg () ControlAnn])
next bbs = do
    nextBs <- addControlFlow bbs
    case nextBs of
        []    -> pure (id, [])
        (b:_) -> pure ((node (caBB b) :), nextBs)

broadcasts :: [BB AArch64 reg freg f2reg a ()] -> FreshM ()
broadcasts [] = pure ()
broadcasts ((BB asms@(asm:_) _):bbs@((BB (Label _ retL:_) _):_)) | C _ l <- last asms = do
    { i <- fm retL; b3 i l
    ; case asm of {Label _ lϵ -> void $ fm lϵ; _ -> pure ()}
    ; broadcasts bbs
    }
broadcasts ((BB (Label _ l:_) _):asms) = fm l *> broadcasts asms
broadcasts (_:asms) = broadcasts asms