aboutsummaryrefslogtreecommitdiff
path: root/CodeGen.hs
diff options
context:
space:
mode:
Diffstat (limited to 'CodeGen.hs')
-rw-r--r--CodeGen.hs86
1 files changed, 57 insertions, 29 deletions
diff --git a/CodeGen.hs b/CodeGen.hs
index d4c9439..774696f 100644
--- a/CodeGen.hs
+++ b/CodeGen.hs
@@ -20,6 +20,7 @@ import RegAlloc
import Utils
import X64 (Register(..), CondCode(..), XRef(..), Ins(..), xref)
import qualified X64 as X64
+import X64Optimiser
data CGState = CGState
@@ -61,10 +62,11 @@ setSpillSize sz = modify $ \s -> s {spillSize = sz}
codegen :: IRProgram -> Error String
codegen (IRProgram vars funcs) = do
x64 <- execCGMonad $ mapM_ codegenFunc funcs
- -- traceShowM x64
+ traceShowM x64
X64.verify x64
varcg <- liftM unlines $ mapM codegenVar vars
- return $ [there|prologue.asm|] ++ "\n" ++ X64.stringify x64 ++
+ x64opt <- x64Optimise x64
+ return $ [there|prologue.asm|] ++ "\n" ++ X64.stringify x64opt ++
"\nsection .data\n" ++ (if length vars > 0 then varcg else "db 0 ; keep dyld happy\n")
@@ -96,9 +98,9 @@ codegenFunc (IRFunc _ name al bbs sid) = do
AllocReg reg -> Just reg
AllocMem -> Nothing
- traceShowM temprefsperbb
- traceShowM lifespans
- -- traceM $ "ALLOCATION: " ++ show allocation
+ -- traceShowM temprefsperbb
+ -- traceShowM lifespans
+ traceM $ "ALLOCATION: " ++ show allocation
let nsaves = length usedregs
allocationXref = flip Map.mapWithKey allocation $ \ref alloc -> case alloc of
@@ -133,6 +135,9 @@ findAliasCandidates = concatMap (\(BB _ inss _) -> concatMap goI inss)
where
goI :: IRIns -> [(Ref, Ref)]
goI (IMov d s) = [(d, s)]
+ goI (IAri at d s1 s2)
+ | isCommutative at = [(d, s1), (d, s2)]
+ | otherwise = [(d, s1)]
goI _ = []
findFirstLast :: forall a. (a -> Bool) -> [a] -> Maybe (Int, Int)
@@ -174,7 +179,8 @@ mkmov a@(XReg _ _) b@(XMem _ _ _ _ _) = MOV (xref a) (xref b)
mkmov a@(XReg _ _) b@(XImm _) = MOVi64 (xref a) (xref b)
mkmov a@(XMem _ _ _ _ _) b@(XReg _ _) = MOV (xref a) (xref b)
mkmov a@(XMem _ _ _ _ _) b@(XImm v) | v < 2 ^ (32 :: Int) = MOVi (xref a) (xref b)
-mkmov a b = error $ "Invalid mkmov: " ++ show a ++ "; " ++ show b
+mkmov a b = CALL $ "Invalid mkmov: " ++ show a ++ "; " ++ show b
+-- mkmov a b = error $ "Invalid mkmov: " ++ show a ++ "; " ++ show b
mkcmp :: XRef -> XRef -> X64.Ins
mkcmp a b@(XImm _) = CMPi (xref a) (xref b)
@@ -221,45 +227,56 @@ codegenIns m (ILoad d s) = do
where dm = mkxref d m
sm = mkxref s m
sz = fromIntegral $ refSize d
-codegenIns m (IAri AMul d s) = do
+codegenIns m (IAri AMul d s1 s2) = do
let sz = fromIntegral $ refSize d
- addIns $ mkmov (XReg sz RAX) (mkxref d m)
- addIns $ mkmov (XReg sz RBX) (mkxref s m)
+ addIns $ mkmov (XReg sz RAX) (mkxref s1 m)
+ addIns $ mkmov (XReg sz RBX) (mkxref s2 m)
addIns $ IMULDA (xref $ XReg sz RBX)
addIns $ mkmov (mkxref d m) (XReg sz RAX)
-codegenIns m (IAri ADiv d s) = do
+codegenIns m (IAri ADiv d s1 s2) = do
let sz = fromIntegral $ refSize d
addIns $ XOR (xref $ XReg 4 RDX) (xref $ XReg 4 RDX)
- addIns $ mkmov (XReg sz RAX) (mkxref d m)
- addIns $ mkmov (XReg sz RBX) (mkxref s m)
+ addIns $ mkmov (XReg sz RAX) (mkxref s1 m)
+ addIns $ mkmov (XReg sz RBX) (mkxref s2 m)
addIns $ IDIVDA (xref $ XReg sz RBX)
addIns $ mkmov (mkxref d m) (XReg sz RAX)
-codegenIns m (IAri AMod d s) = do
+codegenIns m (IAri AMod d s1 s2) = do
let sz = fromIntegral $ refSize d
addIns $ XOR (xref $ XReg 4 RDX) (xref $ XReg 4 RDX)
- addIns $ mkmov (XReg sz RAX) (mkxref d m)
- addIns $ mkmov (XReg sz RBX) (mkxref s m)
+ addIns $ mkmov (XReg sz RAX) (mkxref s1 m)
+ addIns $ mkmov (XReg sz RBX) (mkxref s2 m)
addIns $ IDIVDA (xref $ XReg sz RBX)
addIns $ mkmov (mkxref d m) (XReg sz RDX)
-codegenIns m (IAri at d s) = case arithTypeToCondCode at of
+codegenIns m (IAri at d s1 s2) = case arithTypeToCondCode at of
Just cc -> do
- arg2 <- if X64.isXMem dm && X64.isXMem sm
+ arg2 <- if X64.isXMem s1m && X64.isXMem s2m
then do
- addIns $ mkmov (XReg (fromIntegral $ refSize s) RAX) sm
- return $ XReg (fromIntegral $ refSize s) RAX
- else return sm
- addIns $ mkcmp dm arg2
- addIns $ MOVi (xref dm) (xref $ XImm 0)
+ addIns $ mkmov (XReg (fromIntegral $ refSize s2) RAX) s2m
+ return $ XReg (fromIntegral $ refSize s2) RAX
+ else return s2m
+ addIns $ mkcmp s1m arg2
addIns $ SETCC cc (xref $ X64.xrefSetSize 1 dm)
+ addIns $ AND (xref $ X64.xrefSetSize 4 dm) (xref $ XImm 0xff)
Nothing -> do
- arg2 <- if X64.isXMem dm && X64.isXMem sm
+ (_, s1m', s2', s2m') <-
+ if dm == s2m
+ then if dm == s1m
+ then return (s1, s1m, s2, s2m)
+ else if isCommutative at
+ then return (s2, s2m, s1, s1m)
+ else throwError "Noncommutative op with d==s2/=s1"
+ else return (s1, s1m, s2, s2m)
+
+ arg2 <- if X64.isXMem s1m' && X64.isXMem s2m'
then do
- addIns $ mkmov (XReg (fromIntegral $ refSize s) RAX) sm
- return $ XReg (fromIntegral $ refSize s) RAX
- else return sm
+ addIns $ mkmov (XReg (fromIntegral $ refSize s2') RAX) s2m'
+ return $ XReg (fromIntegral $ refSize s2') RAX
+ else return s2m'
+ when (dm /= s1m') $ addIns $ mkmov dm s1m'
addIns $ fromJust (arithTypeToIns at) dm arg2
where dm = mkxref d m
- sm = mkxref s m
+ s1m = mkxref s1 m
+ s2m = mkxref s2 m
codegenIns m (ICall n rs) = do
forM_ (zip (reverse rs) [1::Int ..]) $ \(r, i) ->
let sz = fromIntegral $ refSize r
@@ -328,9 +345,17 @@ arithTypeToIns _ = Nothing
codegenTerm :: AllocMap -> IRTerm -> CGMonad ()
codegenTerm m (IJcc ct a b t e) = do
- addIns $ mkcmp (mkxref a m) (mkxref b m)
+ if X64.isXMem am && X64.isXMem bm
+ then do
+ addIns $ mkmov (XReg (fromIntegral $ refSize b) RAX) bm
+ addIns $ mkcmp am (XReg (fromIntegral $ refSize b) RAX)
+ else do
+ addIns $ mkcmp am bm
addIns $ JCC (cmpTypeToCondCode ct) (".bb" ++ show t)
addIns $ JMP (".bb" ++ show e)
+ where
+ am = mkxref a m
+ bm = mkxref b m
codegenTerm _ (IJmp i) = addIns $ JMP (".bb" ++ show i)
codegenTerm _ IRet = do
spillsz <- gets spillSize
@@ -363,7 +388,10 @@ collectTempRefs bbs =
listRefsIns (IMov a b) = [[LA.Read b], [LA.Write a]]
listRefsIns (IStore a b) = [[LA.Read a, LA.Read b]]
listRefsIns (ILoad a b) = [[LA.Read b], [LA.Write a]]
- listRefsIns (IAri _ a b) = [[LA.Write a, LA.Read b]]
+ listRefsIns (IAri at a b c)
+ -- if not commutative, we don't want to have to xchg the operands
+ | isCommutative at = [[LA.Read b, LA.Read c], [LA.Write a]]
+ | otherwise = [[LA.Read b], [LA.Read c, LA.Write a]]
listRefsIns (ICall _ l) = [map LA.Read l]
listRefsIns (ICallr a _ l) = [LA.Write a : map LA.Read l]
listRefsIns (IResize a b) = [[LA.Read b], [LA.Write a]]