packages feed

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

{-# OPTIONS_GHC -cpp #-}
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE GADTs #-}
module Llvm.Pass.Mem2Reg (mem2reg) where

import Compiler.Hoopl
import Llvm.Data.Ir
import qualified Data.Map as Dm
import qualified Data.Set as Ds
import Control.Monad
import Llvm.Pass.Rewriter (rwNode,nodeToGraph)
import Prelude hiding(lookup)
#ifdef DEBUG
import Debug.Trace
#endif


-- | TODO: describe in details what this pass is doing
type Mem2RegFact = Dm.Map LValue (WithTop Value)

data LValue = Mem LocalId
            | Ref LocalId
            deriving (Eq, Show, Ord)

mem2RegLattice :: DataflowLattice Mem2RegFact
mem2RegLattice = DataflowLattice { fact_name = "Mem 2 Reg"
                                 , fact_bot = Dm.empty
                                 , fact_join = joinMaps (extendJoinDomain factAdd)
                                 }
  where
    factAdd _ (OldFact old) (NewFact new)
      = if new == old then (NoChange, PElem new)
        else (SomeChange, Top)

isReg :: FwdTransfer (Node a) Mem2RegFact
isReg = mkFTransfer ft

ft :: (Node a) e x -> Mem2RegFact -> Fact x Mem2RegFact
ft (Nlabel _) f = f
ft (Pinst _) f = f
ft (Cinst cinst) f = cinstft cinst f
ft n@(Tinst tinst) f = tinstft n tinst f
 

tinstft :: (Node a) O C -> TerminatorInstWithDbg -> Mem2RegFact -> Fact C Mem2RegFact
tinstft n t@(TerminatorInstWithDbg term _) f =  
  let targets = successors n -- targetOf term
  in case targets of
    [] -> mapEmpty
    l -> mkFactBase mem2RegLattice
         (map (\x -> (x, f)) l)

cinstft :: CInstWithDbg -> Mem2RegFact -> Fact O Mem2RegFact
cinstft = undefined

{-
cinstft (ComputingInstWithDbg (ComputingInst lhs rhs) _) f = cinstft' lhs rhs f


cinstft' :: Maybe GlobalOrLocalId -> Rhs -> Mem2RegFact -> Fact O Mem2RegFact
cinstft' lhs (RmO m) f = memOp lhs m f
cinstft' lhs (Re (Ev tv)) f = maybe f (\a -> let TypedData _ v = tv in
                                        case a of
                                          GolG _ -> f
                                          GolL s -> Dm.insert (Ref $ localIdToLstring s) (PElem v) f) lhs
cinstft' _ (Re _) f = f
cinstft' _ _ f = f


memOp :: Maybe GlobalOrLocalId -> MemOp -> Mem2RegFact -> Fact O Mem2RegFact
memOp (Just (GolL lhs)) (Allocate _ _ Nothing _) f = insert (Mem $ localIdToLstring lhs) Top f
memOp _ (Store _ (TypedData _ v1) (TypedData _ (Pointer (VgOl (GolL ptr)))) _ _) f =
    let x = Mem $ localIdToLstring ptr
    in if (x `Dm.member` f) then insert x (PElem v1) f
       else f
memOp _ (StoreAtomic _ _ (TypedData _ v1) (TypedData _ (Pointer (VgOl (GolL ptr)))) _) f =
    let x = Mem $ localIdToLstring ptr
    in if (x `Dm.member` f) then insert x (PElem v1) f
       else f
memOp _ _ f = f
-}

insert :: Ord k => k -> v -> Dm.Map k v -> Dm.Map k v
#ifdef DEBUG
insert x v1 f | trace ("insert " ++ (show x) ++ "->" ++ (show v1)) False = undefined
#endif
insert x v1 f = Dm.insert x v1 f

badAss :: Monad m => (Value -> Maybe Value) -> Node a e x -> m (Maybe (Node a e x))
badAss f node = return (rwNode f node)


mem2Reg :: forall a.forall m . FuelMonad m => FwdRewrite m (Node a) Mem2RegFact
mem2Reg = mkFRewrite cp
    where
      -- each node is rewritten to a one node graph.
      cp :: FuelMonad m => Node a e x -> Mem2RegFact -> m (Maybe (Graph (Node a) e x))
      cp node f = do { x <- badAss (lookup f) node
                     ; return $ liftM {-Maybe-} nodeToGraph x
                     }

      lookup :: Mem2RegFact -> Value -> Maybe Value
      lookup f x = do { x' <- case x of
                           Val_ssa s -> Just $ Ref s
                           -- Deref (Pointer (VgOl (GolL s))) -> Just $ Mem $ localIdToLstring s
                           _ -> Nothing
                       ;  case Dm.lookup x' f of
                            Just (PElem v) -> Just v
                            _ -> Nothing
                       }




mem2RegPass :: forall a. forall m. FuelMonad m => FwdPass m (Node a) Mem2RegFact
mem2RegPass = FwdPass { fp_lattice = mem2RegLattice
                      , fp_transfer = isReg
                      , fp_rewrite = mem2Reg
                      }


mem2reg :: (CheckpointMonad m, FuelMonad m) => Ds.Set (Dtype, GlobalId) -> Label -> Graph (Node a) C C -> m (Graph (Node a) C C)
mem2reg _ entry graph =
  do { (graph', _, _) <- analyzeAndRewriteFwd fwd (JustC [entry]) graph
                         (mapSingleton entry (Dm.empty)) -- initFact gs))
     ; return graph'
     }
  where fwd = mem2RegPass -- debugFwdJoins trace (const True) mem2RegPas