diff options
Diffstat (limited to 'X64Optimiser.hs')
-rw-r--r-- | X64Optimiser.hs | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/X64Optimiser.hs b/X64Optimiser.hs index fa5d113..195389f 100644 --- a/X64Optimiser.hs +++ b/X64Optimiser.hs @@ -1,6 +1,7 @@ module X64Optimiser(x64Optimise) where import Data.List +import Data.Maybe import Defs import X64 @@ -9,7 +10,10 @@ import X64 x64Optimise :: Asm -> Error Asm x64Optimise asm = return $ - funcopt optCoalesceInstructions $ + funcopt optSimpleInstructions $ + funcopt optDoubleAdd $ + funcopt optMergeRSP $ + funcopt optMergeRSP $ -- #HACK (sometimes needed to eliminate all rsp arithmetic) optUnnecessaryJumps $ funcopt optSimpleInstructions $ asm @@ -35,10 +39,12 @@ optSimpleInstructions (name, inss) = (name, concat $ map goI inss) goI (MOVi (Reg (XReg 8 r)) (Imm (XImm 0))) = [XOR (RegMem (XReg 4 r)) (RegMemImm (XReg 4 r))] goI (MOVi (Reg a) (Imm (XImm 0))) = [XOR (RegMem a) (RegMemImm a)] goI (MOVSX (Reg a) (RegMem b)) | a == b = [] + goI (ADD _ (RegMemImm (XImm 0))) = [] + goI (SUB _ (RegMemImm (XImm 0))) = [] goI ins = [ins] -optCoalesceInstructions :: Func -> Func -optCoalesceInstructions (name, inss) = (name, go inss) +optMergeRSP :: Func -> Func +optMergeRSP (name, inss) = (name, go inss) where go :: [Ins] -> [Ins] go [] = [] @@ -76,3 +82,54 @@ optCoalesceInstructions (name, inss) = (name, go inss) XMem _ _ (_, RSP) _ _ -> Nothing x@(XReg _ _) -> Just x x@(XMem _ _ _ _ _) -> Just x + +optDoubleAdd :: Func -> Func +optDoubleAdd (name, inss) = (name, go inss) + where + go :: [Ins] -> [Ins] + go [] = [] + go (add@(ADD (RegMem xreg@(XReg _ xregReg)) (RegMemImm (XImm _))) : rest) = + let midx = flip findIndex rest $ \ins -> case ins of + ADD (RegMem xreg2@(XReg _ _)) (RegMemImm (XImm _)) | xreg == xreg2 -> True + SUB (RegMem xreg2@(XReg _ _)) (RegMemImm (XImm _)) | xreg == xreg2 -> True + _ -> False + in case midx of + Nothing -> add : go rest + Just idx -> if all (canSkip xregReg) (take idx rest) + then go $ merge add (rest !! idx) : take idx rest ++ drop (idx + 1) rest + else add : go rest + go (ins : rest) = ins : go rest + + canSkip :: Register -> Ins -> Bool + canSkip _ (CALL _) = False + canSkip _ (JMP _) = False + canSkip _ (JCC _ _) = False + canSkip _ RET = False + canSkip reg ins = + isJust $ xrefMapM (\y -> if y `containsReg` reg then Nothing else Just y) ins + + containsReg :: XRef -> Register -> Bool + containsReg (XReg _ r) reg | r == reg = True + containsReg (XMem _ (Just r) _ _ _) reg | r == reg = True + containsReg (XMem _ _ (s, r) _ _) reg | s /= 0 && r == reg = True + containsReg _ _ = False + + merge :: Ins -> Ins -> Ins + merge ins1 ins2 = + let e1 = effectOf ins1 + e2 = effectOf ins2 + dst1 = destOf ins1 + dst2 = destOf ins2 + in if dst1 == dst2 + then ADD (RegMem dst1) (RegMemImm $ XImm $ e1 + e2) + else undefined + + effectOf :: Ins -> Offset + effectOf (ADD _ (RegMemImm (XImm i))) = i + effectOf (SUB _ (RegMemImm (XImm i))) = -i + effectOf _ = undefined + + destOf :: Ins -> XRef + destOf (ADD (RegMem d) _) = d + destOf (SUB (RegMem d) _) = d + destOf _ = undefined |