+{-# OPTIONS -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
+-- for details
+
-----------------------------------------------------------------------------
--
-- Machine-specific parts of the register allocator
patchJump,
isRegRegMove,
+ JumpDest, canShortcut, shortcutJump, shortcutStatic,
+
maxSpillSlots,
mkSpillInstr,
mkLoadInstr,
#include "HsVersions.h"
-import Cmm ( BlockId )
+import BlockId
+import Cmm
+import CLabel
import MachOp ( MachRep(..), wordRep )
import MachInstrs
import MachRegs
import Outputable
import Constants ( rESERVED_C_STACK_BYTES )
-import FastTypes
+import FastBool
-- -----------------------------------------------------------------------------
-- RegUsage type
#if alpha_TARGET_ARCH
regUsage instr = case instr of
+ SPILL reg slot -> usage ([reg], [])
+ RELOAD slot reg -> usage ([], [reg])
LD B reg addr -> usage (regAddr addr, [reg, t9])
LD Bu reg addr -> usage (regAddr addr, [reg, t9])
-- LD W reg addr -> usage (regAddr addr, [reg, t9]) : UNUSED
IDIV sz op -> mkRU (eax:edx:use_R op) [eax,edx]
AND sz src dst -> usageRM src dst
OR sz src dst -> usageRM src dst
+ XOR sz (OpReg src) (OpReg dst)
+ | src == dst -> mkRU [] [dst]
XOR sz src dst -> usageRM src dst
NOT sz op -> usageM op
NEGI sz op -> usageM op
CMP sz src dst -> mkRUR (use_R src ++ use_R dst)
SETCC cond op -> mkRU [] (def_W op)
JXX cond lbl -> mkRU [] []
+ JXX_GBL cond lbl -> mkRU [] []
JMP op -> mkRUR (use_R op)
JMP_TBL op ids -> mkRUR (use_R op)
CALL (Left imm) params -> mkRU params callClobberedRegs
GABS sz src dst -> mkRU [src] [dst]
GNEG sz src dst -> mkRU [src] [dst]
GSQRT sz src dst -> mkRU [src] [dst]
- GSIN sz src dst -> mkRU [src] [dst]
- GCOS sz src dst -> mkRU [src] [dst]
- GTAN sz src dst -> mkRU [src] [dst]
+ GSIN sz _ _ src dst -> mkRU [src] [dst]
+ GCOS sz _ _ src dst -> mkRU [src] [dst]
+ GTAN sz _ _ src dst -> mkRU [src] [dst]
#endif
#if x86_64_TARGET_ARCH
CVTSS2SD src dst -> mkRU [src] [dst]
CVTSD2SS src dst -> mkRU [src] [dst]
- CVTSS2SI src dst -> mkRU (use_R src) [dst]
- CVTSD2SI src dst -> mkRU (use_R src) [dst]
+ CVTTSS2SIQ src dst -> mkRU (use_R src) [dst]
+ CVTTSD2SIQ src dst -> mkRU (use_R src) [dst]
CVTSI2SS src dst -> mkRU (use_R src) [dst]
CVTSI2SD src dst -> mkRU (use_R src) [dst]
FDIV sz src dst -> usageRM src dst
COMMENT _ -> noUsage
DELTA _ -> noUsage
+ SPILL reg slot -> mkRU [reg] []
+ RELOAD slot reg -> mkRU [] [reg]
_other -> panic "regUsage: unrecognised instr"
where
-#if x86_64_TARGET_ARCH
- -- call parameters: include %eax, because it is used
- -- to pass the number of SSE reg arguments to varargs fns.
- params = eax : allArgRegs ++ allFPArgRegs
-#endif
-
-- 2 operand form; first operand Read; second Written
usageRW :: Operand -> Operand -> RegUsage
usageRW op (OpReg reg) = mkRU (use_R op) [reg]
#if sparc_TARGET_ARCH
regUsage instr = case instr of
+ SPILL reg slot -> usage ([reg], [])
+ RELOAD slot reg -> usage ([], [reg])
+
LD sz addr reg -> usage (regAddr addr, [reg])
ST sz reg addr -> usage (reg : regAddr addr, [])
ADD x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
#if powerpc_TARGET_ARCH
regUsage instr = case instr of
+ SPILL reg slot -> usage ([reg], [])
+ RELOAD slot reg -> usage ([], [reg])
+
LD sz reg addr -> usage (regAddr addr, [reg])
LA sz reg addr -> usage (regAddr addr, [reg])
ST sz reg addr -> usage (reg : regAddr addr, [])
CMP sz reg ri -> usage (reg : regRI ri,[])
CMPL sz reg ri -> usage (reg : regRI ri,[])
BCC cond lbl -> noUsage
+ BCCFAR cond lbl -> noUsage
MTCTR reg -> usage ([reg],[])
BCTR targets -> noUsage
BL imm params -> usage (params, callClobberedRegs)
JMP_TBL _ ids -> ids ++ acc
#elif powerpc_TARGET_ARCH
BCC _ id -> id : acc
+ BCCFAR _ id -> id : acc
BCTR targets -> targets ++ acc
#endif
_other -> acc
JMP_TBL op ids -> error "Cannot patch JMP_TBL"
#elif powerpc_TARGET_ARCH
BCC cc id | id == old -> BCC cc new
+ BCCFAR cc id | id == old -> BCCFAR cc new
BCTR targets -> error "Cannot patch BCTR"
#endif
_other -> insn
+data JumpDest = DestBlockId BlockId | DestImm Imm
+
+canShortcut :: Instr -> Maybe JumpDest
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
+canShortcut (JXX ALWAYS id) = Just (DestBlockId id)
+canShortcut (JMP (OpImm imm)) = Just (DestImm imm)
+#endif
+canShortcut _ = Nothing
+
+shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
+shortcutJump fn insn@(JXX cc id) =
+ case fn id of
+ Nothing -> insn
+ Just (DestBlockId id') -> shortcutJump fn (JXX cc id')
+ Just (DestImm imm) -> shortcutJump fn (JXX_GBL cc imm)
+#endif
+shortcutJump fn other = other
+
+-- Here because it knows about JumpDest
+shortcutStatic :: (BlockId -> Maybe JumpDest) -> CmmStatic -> CmmStatic
+shortcutStatic fn (CmmStaticLit (CmmLabel lab))
+ | Just uq <- maybeAsmTemp lab
+ = CmmStaticLit (CmmLabel (shortBlockId fn (BlockId uq)))
+shortcutStatic fn (CmmStaticLit (CmmLabelDiffOff lbl1 lbl2 off))
+ | Just uq <- maybeAsmTemp lbl1
+ = CmmStaticLit (CmmLabelDiffOff (shortBlockId fn (BlockId uq)) lbl2 off)
+ -- slightly dodgy, we're ignoring the second label, but this
+ -- works with the way we use CmmLabelDiffOff for jump tables now.
+shortcutStatic fn other_static
+ = other_static
+
+shortBlockId fn blockid@(BlockId uq) =
+ case fn blockid of
+ Nothing -> mkAsmTempLabel uq
+ Just (DestBlockId blockid') -> shortBlockId fn blockid'
+ Just (DestImm (ImmCLbl lbl)) -> lbl
+ _other -> panic "shortBlockId"
+
-- -----------------------------------------------------------------------------
-- 'patchRegs' function
#if alpha_TARGET_ARCH
patchRegs instr env = case instr of
+ SPILL reg slot -> SPILL (env reg) slot
+ RELOAD slot reg -> RELOAD slot (env reg)
LD sz reg addr -> LD sz (env reg) (fixAddr addr)
LDA reg addr -> LDA (env reg) (fixAddr addr)
LDAH reg addr -> LDAH (env reg) (fixAddr addr)
GABS sz src dst -> GABS sz (env src) (env dst)
GNEG sz src dst -> GNEG sz (env src) (env dst)
GSQRT sz src dst -> GSQRT sz (env src) (env dst)
- GSIN sz src dst -> GSIN sz (env src) (env dst)
- GCOS sz src dst -> GCOS sz (env src) (env dst)
- GTAN sz src dst -> GTAN sz (env src) (env dst)
+ GSIN sz l1 l2 src dst -> GSIN sz l1 l2 (env src) (env dst)
+ GCOS sz l1 l2 src dst -> GCOS sz l1 l2 (env src) (env dst)
+ GTAN sz l1 l2 src dst -> GTAN sz l1 l2 (env src) (env dst)
#endif
#if x86_64_TARGET_ARCH
CVTSS2SD src dst -> CVTSS2SD (env src) (env dst)
CVTSD2SS src dst -> CVTSD2SS (env src) (env dst)
- CVTSS2SI src dst -> CVTSS2SI (patchOp src) (env dst)
- CVTSD2SI src dst -> CVTSD2SI (patchOp src) (env dst)
+ CVTTSS2SIQ src dst -> CVTTSS2SIQ (patchOp src) (env dst)
+ CVTTSD2SIQ src dst -> CVTTSD2SIQ (patchOp src) (env dst)
CVTSI2SS src dst -> CVTSI2SS (patchOp src) (env dst)
CVTSI2SD src dst -> CVTSI2SD (patchOp src) (env dst)
FDIV sz src dst -> FDIV sz (patchOp src) (patchOp dst)
NOP -> instr
COMMENT _ -> instr
DELTA _ -> instr
+ SPILL reg slot -> SPILL (env reg) slot
+ RELOAD slot reg -> RELOAD slot (env reg)
+
JXX _ _ -> instr
+ JXX_GBL _ _ -> instr
CLTD _ -> instr
_other -> panic "patchRegs: unrecognised instr"
#if sparc_TARGET_ARCH
patchRegs instr env = case instr of
+ SPILL reg slot -> SPILL (env reg) slot
+ RELOAD slot reg -> RELOAD slot (env reg)
LD sz addr reg -> LD sz (fixAddr addr) (env reg)
ST sz reg addr -> ST sz (env reg) (fixAddr addr)
ADD x cc r1 ar r2 -> ADD x cc (env r1) (fixRI ar) (env r2)
#if powerpc_TARGET_ARCH
patchRegs instr env = case instr of
+ SPILL reg slot -> SPILL (env reg) slot
+ RELOAD slot reg -> RELOAD slot (env reg)
+
LD sz reg addr -> LD sz (env reg) (fixAddr addr)
LA sz reg addr -> LA sz (env reg) (fixAddr addr)
ST sz reg addr -> ST sz (env reg) (fixAddr addr)
CMP sz reg ri -> CMP sz (env reg) (fixRI ri)
CMPL sz reg ri -> CMPL sz (env reg) (fixRI ri)
BCC cond lbl -> BCC cond lbl
+ BCCFAR cond lbl -> BCCFAR cond lbl
MTCTR reg -> MTCTR (env reg)
BCTR targets -> BCTR targets
BL imm argRegs -> BL imm argRegs -- argument regs
#elif powerpc_TARGET_ARCH
isRegRegMove (MR dst src) = Just (src,dst)
#else
-#warning ToDo: isRegRegMove
+#error ToDo: isRegRegMove
#endif
isRegRegMove _ = Nothing
-- Generating spill instructions
mkSpillInstr
- :: Reg -- register to spill (should be a real)
+ :: Reg -- register to spill
-> Int -- current stack delta
-> Int -- spill slot to use
-> Instr
mkSpillInstr reg delta slot
- = ASSERT(isRealReg reg)
- let
- off = spillSlotToOffset slot
+ = let off = spillSlotToOffset slot
in
#ifdef alpha_TARGET_ARCH
{-Alpha: spill below the stack pointer (?)-}
RcInteger -> I32;
RcFloat -> F32;
RcDouble -> F64}}
- in ST sz reg (fpRel (- off_w))
+ in ST sz reg (fpRel (negate off_w))
#endif
#ifdef powerpc_TARGET_ARCH
let sz = case regClass reg of
mkLoadInstr
- :: Reg -- register to load (should be a real)
+ :: Reg -- register to load
-> Int -- current stack delta
-> Int -- spill slot to use
-> Instr
mkLoadInstr reg delta slot
- = ASSERT(isRealReg reg)
- let
- off = spillSlotToOffset slot
+ = let off = spillSlotToOffset slot
in
#if alpha_TARGET_ARCH
LD sz dyn (spRel (- (off `div` 8)))
#endif
#elif powerpc_TARGET_ARCH
= MR dst src
+#else
+#error ToDo: mkRegRegMoveInstr
#endif
mkBranchInstr
= 64 + spillSlotSize * slot
| otherwise
= pprPanic "spillSlotToOffset:"
- (text "invalid spill location: " <> int slot)
+ ( text "invalid spill location: " <> int slot
+ $$ text "maxSpillSlots: " <> int maxSpillSlots)