diff options
Diffstat (limited to 'Optimiser.hs')
-rw-r--r-- | Optimiser.hs | 101 |
1 files changed, 65 insertions, 36 deletions
diff --git a/Optimiser.hs b/Optimiser.hs index 61834f8..531bc7d 100644 --- a/Optimiser.hs +++ b/Optimiser.hs @@ -123,6 +123,7 @@ removeDuplicateBlocks (IRFunc rt name al bbs sid) = IRFunc rt name al bbs' sid IJmp i -> IJmp (trans from to i) IRet -> IRet IRetr r -> IRetr r + IUnreachable -> IUnreachable ITermNone -> undefined trans :: (Eq a) => a -> a -> a -> a @@ -190,39 +191,41 @@ movPush (IRFunc rt name al bbs sid) = IRFunc rt name al (map goBB bbs) sid go :: [IRIns] -> IRTerm -> [IRIns] go [] _ = [] - go (ins@(IMov d _) : rest) term + go (IMov d s : rest) term | isJust (find (== d) (findAllRefsInss rest ++ findAllRefsTerm term)) = - push ins rest term + push (d, s) rest term go (ins : rest) term = ins : go rest term - push :: IRIns -> [IRIns] -> IRTerm -> [IRIns] - push mov [] _ = [mov] - push (IMov d s) l _ | d == s = l - push mov@(IMov d s) (ins@(IMov d' s') : rest) term - | d' == d = if d' == s' then push mov rest term else push ins rest term - | d' == s = mov : push (IMov d' (replaceRef d s s')) rest term + push :: (Ref, Ref) -> [IRIns] -> IRTerm -> [IRIns] + push (d, s) [] _ = [IMov d s] + push (d, s) l _ | d == s = l + push mov@(d, s) (IMov d' s' : rest) term + | d' == d = if d' == s' then push mov rest term else push (d', s') rest term + | d' == s = IMov d s : push (d', replaceRef d s s') rest term | otherwise = IMov d' (replaceRef d s s') : push mov rest term - push mov@(IMov d s) (IResize d' s' : rest) term + push mov@(d, s) (IResize d' s' : rest) term | d' == d = IResize d' (replaceRef d s s') : go rest term - | d' == s = mov : IResize d' (replaceRef d s s') : go rest term + | d' == s = IMov d s : IResize d' (replaceRef d s s') : go rest term | otherwise = IResize d' (replaceRef d s s') : push mov rest term - push mov@(IMov d s) (ILoad d' s' : rest) term + push mov@(d, s) (ILoad d' s' : rest) term | d' == d = ILoad d' (replaceRef d s s') : go rest term - | d' == s = mov : ILoad d' (replaceRef d s s') : go rest term + | d' == s = IMov d s : ILoad d' (replaceRef d s s') : go rest term | otherwise = ILoad d' (replaceRef d s s') : push mov rest term - push mov@(IMov d s) (IAri at d' s1' s2' : rest) term + push mov@(d, s) (IAri at d' s1' s2' : rest) term | d' == d = IAri at d' (replaceRef d s s1') (replaceRef d s s2') : go rest term - | d' == s = mov : IAri at d' (replaceRef d s s1') (replaceRef d s s2') : go rest term + | d' == s = IMov d s : IAri at d' (replaceRef d s s1') (replaceRef d s s2') : go rest term | otherwise = IAri at d' (replaceRef d s s1') (replaceRef d s s2') : push mov rest term -- I don't trust going past calls because globals might change. Might be able to -- catch that case, but that will go wrong when more stuff gets added. - -- push mov@(IMov d s) (ins@(ICallr d' _ _) : rest) term - -- | d' == d = mov : ins : go rest term + -- push mov@(d, s) (ins@(ICallr d' _ _) : rest) term + -- | d' == d = IMov d s : ins : go rest term -- | otherwise = replaceRefsIns d s ins : push mov rest term - -- push mov@(IMov d s) (ins@(ICall _ _) : rest) term = replaceRefsIns d s ins : push mov rest term - push mov@(IMov d s) (ins@(IStore _ _) : rest) term = replaceRefsIns d s ins : push mov rest term + -- push mov@(d, s) (ins@(ICall _ _) : rest) term = replaceRefsIns d s ins : push mov rest term + push (d, s) l@(ICallr _ _ _ : _) term = IMov d s : go l term + push (d, s) l@(ICall _ _ : _) term = IMov d s : go l term + push mov@(d, s) (ins@(IStore _ _) : rest) term = replaceRefsIns d s ins : push mov rest term + push (d, s) l@(IDebugger : _) term = IMov d s : go l term push mov (INop : rest) term = push mov rest term - push mov l term = mov : go l term pushT :: IRIns -> IRTerm -> IRTerm pushT (IMov d s) term = replaceRefsTerm d s term @@ -245,15 +248,16 @@ arithPush (IRFunc rt name al allbbs sid) = IRFunc rt name al resbbs sid in foldl (\bbs' tg -> propagateContinue ari tg bbs') resbbs1 tgs propagateContinue :: IRIns -> BB -> [BB] -> [BB] - propagateContinue ari bb _ | traceShow (ari, bb) False = undefined - propagateContinue ari bb@(BB bid _ _) bbs = - let (cont, (inss', [Right term'])) = fmap (span isLeft) $ propagate ari (bbToList bb) + -- propagateContinue ari bb _ | traceShow (ari, bb) False = undefined + propagateContinue ari@(IAri at d s1 s2) bb@(BB bid _ _) bbs = + let (cont, (inss', [Right term'])) = fmap (span isLeft) $ propagate (at, d, s1, s2) (bbToList bb) resbbs1 = replaceBlock bid (BB bid (map (fromLeft undefined) inss') term') bbs in if cont then let tgs = map (flip blockById bbs) $ filter (\b -> length (originBlocks b) == 1) $ jumpTargets term' in foldl (\bbs' tg -> propagateContinue ari tg bbs') resbbs1 tgs else resbbs1 + propagateContinue _ _ _ = undefined blockById :: Id -> [BB] -> BB blockById i bbs = head $ filter (\(BB bid _ _) -> bid == i) bbs @@ -269,7 +273,7 @@ arithPush (IRFunc rt name al allbbs sid) = IRFunc rt name al resbbs sid go :: [Either IRIns IRTerm] -> (Maybe IRIns, [Either IRIns IRTerm]) go [] = (Nothing, []) - go (Left ari@(IAri _ _ _ _) : rest) = case propagate ari rest of + go (Left ari@(IAri at d s1 s2) : rest) = case propagate (at, d, s1, s2) rest of (False, res) -> fmap (Left ari :) $ go res (True, res) -> (Just ari, Left ari : res) go (ins : rest) = fmap (ins :) $ go rest @@ -277,33 +281,33 @@ arithPush (IRFunc rt name al allbbs sid) = IRFunc rt name al resbbs sid bbToList :: BB -> [Either IRIns IRTerm] bbToList (BB _ inss term) = map Left inss ++ [Right term] - propagate :: IRIns -> [Either IRIns IRTerm] -> (Bool, [Either IRIns IRTerm]) + propagate :: (ArithType, Ref, Ref, Ref) -> [Either IRIns IRTerm] -> (Bool, [Either IRIns IRTerm]) propagate _ [] = (True, []) - propagate ari@(IAri _ d s1 s2) (Left ins@(IMov md _) : rest) + propagate ari@(_, d, s1, s2) (Left ins@(IMov md _) : rest) | d /= md && md /= s1 && md /= s2 = fmap (Left ins :) $ propagate ari rest | otherwise = (False, Left ins : rest) - propagate ari@(IAri _ _ _ _) (Left ins@(IStore _ _) : rest) = + propagate ari (Left ins@(IStore _ _) : rest) = fmap (Left ins :) $ propagate ari rest - propagate ari@(IAri _ d s1 s2) (Left ins@(ILoad md _) : rest) + propagate ari@(_, d, s1, s2) (Left ins@(ILoad md _) : rest) | d /= md && md /= s1 && md /= s2 = fmap (Left ins :) $ propagate ari rest | otherwise = (False, Left ins : rest) - propagate ari@(IAri at d s1 s2) (Left ins@(IAri mat md ms1 ms2) : rest) + propagate ari@(at, d, s1, s2) (Left ins@(IAri mat md ms1 ms2) : rest) | d /= md && (at, s1, s2) == (mat, ms1, ms2) = fmap (Left (IMov md d) :) $ propagate ari rest | d /= md && md /= s1 && md /= s2 = fmap (Left ins :) $ propagate ari rest - | otherwise = fmap (Left ins :) $ propagate ins rest + | otherwise = fmap (Left ins :) $ propagate (mat, md, ms1, ms2) rest -- I don't trust going past calls because globals might change. Might be able to -- catch that case, but that will go wrong when more stuff gets added. - -- propagate ari@(IAri _ d s1 s2) (Left ins@(ICall _ mal) : rest) + -- propagate ari@(_, d, s1, s2) (Left ins@(ICall _ mal) : rest) -- | null (intersect [d] mal) = fmap (Left ins :) $ propagate ari rest -- | otherwise = (False, Left ins : rest) - -- propagate ari@(IAri _ d s1 s2) (Left ins@(ICallr md _ mal) : rest) + -- propagate ari@(_, d, s1, s2) (Left ins@(ICallr md _ mal) : rest) -- | null (intersect [d,s1,s2] (md : mal)) = fmap (Left ins :) $ propagate ari rest -- | otherwise = (False, Left ins : rest) - propagate ari@(IAri _ d s1 s2) (Left ins@(IResize md _) : rest) + propagate ari@(_, d, s1, s2) (Left ins@(IResize md _) : rest) | d /= md && md /= s1 && md /= s2 = fmap (Left ins :) $ propagate ari rest | otherwise = (False, Left ins : rest) - propagate ari@(IAri _ _ _ _) (Left INop : rest) = propagate ari rest - propagate (IAri at d s1 s2) (Right term@(IJcc ct r1 r2 i1 i2) : rest) + propagate ari (Left INop : rest) = propagate ari rest + propagate (at, d, s1, s2) (Right term@(IJcc ct r1 r2 i1 i2) : rest) | (r1 == d || r2 == d) && (isConstant r1 || isConstant r2) && at `elem` [AEq, ANeq, AGt, ALt, AGeq, ALeq] = @@ -335,7 +339,14 @@ arithPush (IRFunc rt name al allbbs sid) = IRFunc rt name al resbbs sid _ -> undefined in (True, Right resterm : rest) | otherwise = (True, Right term : rest) - propagate _ l = (False, l) + propagate _ l@(Left (ICall _ _) : _) = (False, l) + propagate _ l@(Left (ICallr _ _ _) : _) = (False, l) + propagate _ l@(Left IDebugger : _) = (False, l) + propagate _ l@(Right (IJmp _) : _) = (True, l) + propagate _ l@(Right IRet : _) = (False, l) + propagate _ l@(Right (IRetr _) : _) = (False, l) + propagate _ l@(Right IUnreachable : _) = (False, l) + propagate _ (Right ITermNone : _) = undefined flipCmpType :: CmpType -> CmpType flipCmpType CEq = CEq @@ -344,6 +355,10 @@ flipCmpType CGt = CLt flipCmpType CLt = CGt flipCmpType CGeq = CLeq flipCmpType CLeq = CGeq +flipCmpType CUGt = CULt +flipCmpType CULt = CUGt +flipCmpType CUGeq = CULeq +flipCmpType CULeq = CUGeq invertCmpType :: CmpType -> CmpType invertCmpType CEq = CNeq @@ -352,6 +367,10 @@ invertCmpType CGt = CLeq invertCmpType CLt = CGeq invertCmpType CGeq = CLt invertCmpType CLeq = CGt +invertCmpType CUGt = CULeq +invertCmpType CULt = CUGeq +invertCmpType CUGeq = CULt +invertCmpType CULeq = CUGt arithTypeToCmpType :: ArithType -> CmpType arithTypeToCmpType AEq = CEq @@ -376,6 +395,7 @@ removeUnusedInstructions (IRFunc rt name al bbs sid) = IRFunc rt name al (map go goI ins@(ICall _ _) = Just ins goI ins@(ICallr _ _ _) = Just ins goI ins@(IResize d _) = pureInstruction d ins + goI IDebugger = Just IDebugger goI INop = Nothing pureInstruction :: Ref -> IRIns -> Maybe IRIns @@ -436,7 +456,10 @@ reorderBlocks (IRFunc rt name al allbbs sid) = IRFunc rt name al resbbs sid chain' = chain ++ [at] in case intersect (jumpTargets term) (map blockIdOf rest) of [] -> [chain'] - tgs -> concatMap (go rest chain') tgs + tgs -> flip concatMap tgs $ \tg -> + if hasUnreachable (fst $ takeBlock tg bbs) + then [] + else go rest chain' tg buildResult :: [[Id]] -> [BB] -> [BB] buildResult _ [] = [] @@ -453,6 +476,10 @@ reorderBlocks (IRFunc rt name al allbbs sid) = IRFunc rt name al resbbs sid | bid == target = (bb, rest) | otherwise = fmap (bb :) $ takeBlock target rest + hasUnreachable :: BB -> Bool + hasUnreachable (BB _ _ IUnreachable) = True + hasUnreachable _ = False + invertJccs :: FuncOptimisation invertJccs (IRFunc rt name al bbs sid) = IRFunc rt name al bbs' sid where @@ -539,6 +566,7 @@ findAllRefsIns (IAri _ a b c) = [a, b, c] findAllRefsIns (ICall _ al) = al findAllRefsIns (ICallr a _ al) = a : al findAllRefsIns (IResize a b) = [a, b] +findAllRefsIns IDebugger = [] findAllRefsIns INop = [] findAllRefsTerm :: IRTerm -> [Ref] @@ -546,6 +574,7 @@ findAllRefsTerm (IJcc _ a b _ _) = [a, b] findAllRefsTerm (IJmp _) = [] findAllRefsTerm IRet = [] findAllRefsTerm (IRetr a) = [a] +findAllRefsTerm IUnreachable = [] findAllRefsTerm ITermNone = undefined -- findAllRefs' :: [BB] -> [Ref] |