packages feed

hLLVM-0.5.0.0: src/Llvm/Pass/Liveness.hs

{-# LANGUAGE ScopedTypeVariables, GADTs #-}

module Llvm.Pass.Liveness (dce) where
import Data.Maybe
import qualified Data.Set as Ds
import qualified Data.List as L

import qualified Compiler.Hoopl as H
import Llvm.Data.Ir
import Llvm.Pass.Uda
import Llvm.Syntax.Printer.IrPrint

type Live = Ds.Set LocalId
liveLattice :: H.DataflowLattice Live
liveLattice = H.DataflowLattice
              { H.fact_name = "Live variables"
              , H.fact_bot = Ds.empty
              , H.fact_join = add
              }
    where add _ (H.OldFact old) (H.NewFact new) = (ch, j)
              where
                j = new `Ds.union` old
                ch= H.changeIf (Ds.size j > Ds.size old)

liveness :: H.BwdTransfer (Node a) Live
liveness = H.mkBTransfer live
  where
    live = undefined
    {-
    live :: Node e x -> H.Fact x Live -> Live
    live (Nlabel _) f = f
    live (Pinst n) f = f `Ds.union` (filterOutGlobalId $ u1ofPinstWithDbg n) `Ds.difference` (filterOutGlobalId $ d1ofPinstWithDbg n)
    -- | FIXME
    -- | this is a very simplistic implementation and it does not consider function calls might have side effects.
    -- | we need to distinguish the uses of a possible side effect computation from the uses of a pure computation.
    live (Cinst n) f = f `Ds.union` (filterOutGlobalId $ u1ofComputingInstWithDbg n) `Ds.difference` (filterOutGlobalId $ d1ofComputingInstWithDbg n)
    live x@(Tinst n) f = let bs = H.successors x
                             f' = foldl (\p -> \l -> p `Ds.union` (fact f l)) Ds.empty bs
                         in f' `Ds.union` (filterOutGlobalId $ u1ofTerminatorInstWithDbg n) `Ds.difference` (filterOutGlobalId $ d1ofTerminatorInstWithDbg n)
--    fact :: FactBase (Ds.Set LocalId) -> Label -> Live
    fact f l = fromMaybe Ds.empty $ H.lookupFact l f
-}

deadAsstElim :: forall a. forall m. H.FuelMonad m => H.BwdRewrite m (Node a) Live
deadAsstElim = H.mkBRewrite d
   where
     d :: Node a e x -> H.Fact x Live -> m (Maybe (H.Graph (Node a) e x))
     d (Cinst n) live = dead n live
     d _ _ = return Nothing


dead :: forall a.forall m. H.FuelMonad m => CInstWithDbg -> H.Fact H.O Live -> m (Maybe (H.Graph (Node a) H.O H.O))
dead (CInstWithDbg ci _) live = deadCi ci live


deadCi :: forall a.forall m. H.FuelMonad m => CInst -> H.Fact H.O Live -> m (Maybe (H.Graph (Node a) H.O H.O))
deadCi = undefined
{-
deadCi (ComputingInst Nothing (RmO m)) live = deadRmo m live
deadCi (ComputingInst Nothing (Call _ cs)) live = deadCallSite cs live
deadCi (ComputingInst _ (LandingPad _ _ _ _ _)) _ = return Nothing
deadCi (ComputingInst lhsOpt _) live = case lhsOpt of
                                         Just (GolL x) | not (x `Ds.member` live) -> return $ Just H.emptyGraph
                                         _  -> return Nothing


deadRmo :: forall m. H.FuelMonad m => MemOp -> H.Fact H.O Live -> m (Maybe (H.Graph Node H.O H.O))
deadRmo inst live = case inst of
  (Store _ _ (TypedData _ (Pointer v)) _ _) -> case localIdOfValue v of
    Just x | not (x `Ds.member` live) -> return $ Just H.emptyGraph
    _ -> return Nothing
  (StoreAtomic _ _ _ (TypedData _ (Pointer v)) _) -> case localIdOfValue v of
    Just x | not (x `Ds.member` live) -> return $ Just H.emptyGraph
    _ -> return Nothing
  _ -> return Nothing
  where localIdOfValue (VgOl (GolL x)) = Just x
        localIdOfValue _ = Nothing
-}

isDeclare :: FunName -> Bool
isDeclare (FunNameGlobal (GolG gl)) | (render $ printIr gl) == "@llvm.dbg.declare" = True
isDeclare _ = False


isDeadAP :: H.Fact H.O Live -> ActualParam -> Bool
isDeadAP = undefined
{-
isDeadAP live ap  = let u = filterOutGlobalId $ u1 $ uDofActualParam ap
                        dif = u `Ds.intersection` live
                    in dif == Ds.empty
-}

deadCallSite :: forall a.forall m. H.FuelMonad m => CallSite -> H.Fact H.O Live -> m (Maybe (H.Graph (Node a) H.O H.O))
deadCallSite (CsFun _ _ _ fn ap _) live | isDeclare fn =
  if L.all (isDeadAP live) ap then return $ Just H.emptyGraph
  else return Nothing
deadCallSite _ _ = return Nothing



filterOutGlobalId :: Ds.Set GlobalOrLocalId -> Ds.Set LocalId
filterOutGlobalId s = Ds.foldl (\a b -> case b of
                                         GolL l -> Ds.insert l a
                                         _ -> a) Ds.empty s





dcePass :: forall a. forall m. H.FuelMonad m => H.BwdPass m (Node a) Live
dcePass = H.BwdPass { H.bp_lattice = liveLattice
                    , H.bp_transfer = liveness
                    , H.bp_rewrite = deadAsstElim
                    }

dce :: (H.CheckpointMonad m, H.FuelMonad m) => Ds.Set (Dtype, GlobalId) -> Label -> H.Graph (Node a) H.C H.C -> m (H.Graph (Node a) H.C H.C)
dce _ entry graph =
  do { (graph', _, _) <- H.analyzeAndRewriteBwd bwd (H.JustC [entry]) graph
                         H.mapEmpty
     ; return graph'
     }
  where bwd = dcePass