aboutsummaryrefslogtreecommitdiff
path: root/X64Optimiser.hs
diff options
context:
space:
mode:
Diffstat (limited to 'X64Optimiser.hs')
-rw-r--r--X64Optimiser.hs53
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