diff options
Diffstat (limited to 'X64Optimiser.hs')
-rw-r--r-- | X64Optimiser.hs | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/X64Optimiser.hs b/X64Optimiser.hs index 746d88f..fa5d113 100644 --- a/X64Optimiser.hs +++ b/X64Optimiser.hs @@ -1,5 +1,7 @@ module X64Optimiser(x64Optimise) where +import Data.List + import Defs import X64 @@ -7,6 +9,7 @@ import X64 x64Optimise :: Asm -> Error Asm x64Optimise asm = return $ + funcopt optCoalesceInstructions $ optUnnecessaryJumps $ funcopt optSimpleInstructions $ asm @@ -26,10 +29,50 @@ optSimpleInstructions :: Func -> Func optSimpleInstructions (name, inss) = (name, concat $ map goI inss) where goI :: Ins -> [Ins] - goI (MOV (RegMem a) (RegMem b)) | a == b = [] - goI (MOVi (RegMem (XReg 8 r)) (Imm (XImm 0))) = [XOR (RegMem (XReg 4 r)) (RegMemImm (XReg 4 r))] - goI (MOVi (RegMem a@(XReg _ _)) (Imm (XImm 0))) = [XOR (RegMem a) (RegMemImm a)] - goI (MOVi64 (Reg (XReg 8 r)) (Imm (XImm 0))) = [XOR (RegMem (XReg 4 r)) (RegMemImm (XReg 4 r))] - goI (MOVi64 (Reg a) (Imm (XImm 0))) = [XOR (RegMem a) (RegMemImm a)] + goI (MOV (RegMem a) (RegMemImm b)) | a == b = [] + goI (MOV (RegMem (XReg 8 r)) (RegMemImm (XImm 0))) = [XOR (RegMem (XReg 4 r)) (RegMemImm (XReg 4 r))] + goI (MOV (RegMem a@(XReg _ _)) (RegMemImm (XImm 0))) = [XOR (RegMem a) (RegMemImm a)] + 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 ins = [ins] + +optCoalesceInstructions :: Func -> Func +optCoalesceInstructions (name, inss) = (name, go inss) + where + go :: [Ins] -> [Ins] + go [] = [] + go (add@(ADD (RegMem (XReg 8 RSP)) (RegMemImm (XImm n))) : rest) = + let midx = flip findIndex rest $ \ins -> case ins of + SUB (RegMem (XReg 8 RSP)) (RegMemImm (XImm n')) | n' == n -> True + _ -> False + in case midx of + Nothing -> add : go rest + Just idx -> case mapM (shiftRSP n) (take idx rest) of + Nothing -> add : go rest + Just shifted -> shifted ++ go (drop (idx + 1) rest) + go (MOV (RegMem (XMem 8 (Just RSP) (0, _) Nothing (-8))) (RegMemImm r@(XReg 8 _)) : + SUB (RegMem (XReg 8 RSP)) (RegMemImm (XImm 8)) : + rest) = + PUSH (RegMemImm r) : go rest + go (ins : rest) = ins : go rest + + isNonLinear :: Ins -> Bool + isNonLinear (CALL _) = True + isNonLinear (JMP _) = True + isNonLinear (JCC _ _) = True + isNonLinear RET = True + isNonLinear _ = False + + shiftRSP :: Offset -> Ins -> Maybe Ins + shiftRSP _ ins | isNonLinear ins = Nothing + shiftRSP off ins = flip xrefMapM ins $ \thexref -> case thexref of + XMem sz (Just RSP) (0, zero) lbl o -> Just $ XMem sz (Just RSP) (0, zero) lbl (o + off) + XMem sz Nothing (c, RSP) lbl o -> Just $ XMem sz Nothing (c, RSP) lbl (o + (fromIntegral c) * off) + XMem sz (Just RSP) (c, RSP) lbl o -> Just $ XMem sz (Just RSP) (c, RSP) lbl (o + (fromIntegral c + 1) * off) + x@(XImm _) -> Just x + XReg _ RSP -> Nothing + XMem _ (Just RSP) _ _ _ -> Nothing + XMem _ _ (_, RSP) _ _ -> Nothing + x@(XReg _ _) -> Just x + x@(XMem _ _ _ _ _) -> Just x |