X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2FnativeGen%2FX86%2FRegs.hs;h=64d835b2ebe1bff7d5b3a75b94fcb224d1088f5f;hp=3432090ff73975d591c60269b90660560ff18450;hb=a2a67cd520b9841114d69a87a423dabcb3b4368e;hpb=9de520b7194c9d759147db98deb3cd8d47d0de76 diff --git a/compiler/nativeGen/X86/Regs.hs b/compiler/nativeGen/X86/Regs.hs index 3432090..64d835b 100644 --- a/compiler/nativeGen/X86/Regs.hs +++ b/compiler/nativeGen/X86/Regs.hs @@ -1,14 +1,7 @@ module X86.Regs ( - - -- sizes - Size(..), - intSize, - floatSize, - isFloatSize, - wordSize, - cmmTypeSize, - sizeToWidth, - mkVReg, + -- squeese functions for the graph allocator + virtualRegSqueeze, + realRegSqueeze, -- immediates Imm(..), @@ -25,33 +18,30 @@ module X86.Regs ( allArgRegs, callClobberedRegs, allMachRegNos, - regClass, + classOfRealReg, showReg, -- machine specific EABase(..), EAIndex(..), addrModeRegs, -#if i386_TARGET_ARCH - -- part of address mode. shared for both arches. eax, ebx, ecx, edx, esi, edi, ebp, esp, fake0, fake1, fake2, fake3, fake4, fake5, -#endif -#if x86_64_TARGET_ARCH - -- part of address mode. shared for both arches. - ripRel, - allFPArgRegs, - + rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, - eax, ebx, ecx, edx, esi, edi, ebp, esp, - r8, r9, r10, r11, r12, r13, r14, r15, + r8, r9, r10, r11, r12, r13, r14, r15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm, -#endif + + ripRel, + allFPArgRegs, -- horror show freeReg, - globalRegMaybe + globalRegMaybe, + + get_GlobalReg_reg_or_addr, + allocatableRegs ) where @@ -64,90 +54,124 @@ where -- HACK: go for the max #endif -#include "../includes/MachRegs.h" +#include "../includes/stg/MachRegs.h" -import RegsBase +import Reg +import RegClass +import CgUtils ( get_GlobalReg_addr ) import BlockId import Cmm import CLabel ( CLabel ) import Pretty -import Outputable ( Outputable(..), pprPanic, panic ) -import qualified Outputable -import Unique +import Outputable ( panic ) +import FastTypes import FastBool --- ----------------------------------------------------------------------------- --- Sizes on this architecture --- --- A Size is usually a combination of width and class - --- It looks very like the old MachRep, but it's now of purely local --- significance, here in the native code generator. You can change it --- without global consequences. --- --- A major use is as an opcode qualifier; thus the opcode --- mov.l a b --- might be encoded --- MOV II32 a b --- where the Size field encodes the ".l" part. - --- ToDo: it's not clear to me that we need separate signed-vs-unsigned sizes --- here. I've removed them from the x86 version, we'll see what happens --SDM - --- ToDo: quite a few occurrences of Size could usefully be replaced by Width - -data Size - = II8 | II16 | II32 | II64 | FF32 | FF64 | FF80 - deriving Eq - -intSize, floatSize :: Width -> Size -intSize W8 = II8 -intSize W16 = II16 -intSize W32 = II32 -intSize W64 = II64 -intSize other = pprPanic "MachInstrs.intSize" (ppr other) - - -floatSize W32 = FF32 -floatSize W64 = FF64 -floatSize other = pprPanic "MachInstrs.intSize" (ppr other) - - -isFloatSize :: Size -> Bool -isFloatSize FF32 = True -isFloatSize FF64 = True -isFloatSize FF80 = True -isFloatSize _ = False - - -wordSize :: Size -wordSize = intSize wordWidth - -cmmTypeSize :: CmmType -> Size -cmmTypeSize ty | isFloatType ty = floatSize (typeWidth ty) - | otherwise = intSize (typeWidth ty) +#if defined(i386_TARGET_ARCH) || defined(x86_64_TARGET_ARCH) +import Constants +#endif -sizeToWidth :: Size -> Width -sizeToWidth II8 = W8 -sizeToWidth II16 = W16 -sizeToWidth II32 = W32 -sizeToWidth II64 = W64 -sizeToWidth FF32 = W32 -sizeToWidth FF64 = W64 -sizeToWidth _ = panic "MachInstrs.sizeToWidth" +-- | regSqueeze_class reg +-- Calculuate the maximum number of register colors that could be +-- denied to a node of this class due to having this reg +-- as a neighbour. +-- +{-# INLINE virtualRegSqueeze #-} +virtualRegSqueeze :: RegClass -> VirtualReg -> FastInt + +virtualRegSqueeze cls vr + = case cls of + RcInteger + -> case vr of + VirtualRegI{} -> _ILIT(1) + VirtualRegHi{} -> _ILIT(1) + VirtualRegD{} -> _ILIT(0) + VirtualRegF{} -> _ILIT(0) + + -- We don't use floats on this arch, but we can't + -- return error because the return type is unboxed... + RcFloat + -> case vr of + VirtualRegI{} -> _ILIT(0) + VirtualRegHi{} -> _ILIT(0) + VirtualRegD{} -> _ILIT(0) + VirtualRegF{} -> _ILIT(0) + + RcDouble + -> case vr of + VirtualRegI{} -> _ILIT(0) + VirtualRegHi{} -> _ILIT(0) + VirtualRegD{} -> _ILIT(1) + VirtualRegF{} -> _ILIT(0) + +{-# INLINE realRegSqueeze #-} +realRegSqueeze :: RegClass -> RealReg -> FastInt + +#if defined(i386_TARGET_ARCH) +realRegSqueeze cls rr + = case cls of + RcInteger + -> case rr of + RealRegSingle regNo + | regNo < 8 -> _ILIT(1) -- first fp reg is 8 + | otherwise -> _ILIT(0) + + RealRegPair{} -> _ILIT(0) + + -- We don't use floats on this arch, but we can't + -- return error because the return type is unboxed... + RcFloat + -> case rr of + RealRegSingle regNo + | regNo < 8 -> _ILIT(0) + | otherwise -> _ILIT(0) + + RealRegPair{} -> _ILIT(0) + + RcDouble + -> case rr of + RealRegSingle regNo + | regNo < 8 -> _ILIT(0) + | otherwise -> _ILIT(1) + + RealRegPair{} -> _ILIT(0) + +#elif defined(x86_64_TARGET_ARCH) +realRegSqueeze cls rr + = case cls of + RcInteger + -> case rr of + RealRegSingle regNo + | regNo < 16 -> _ILIT(1) -- first xmm reg is 16 + | otherwise -> _ILIT(0) + + RealRegPair{} -> _ILIT(0) + + -- We don't use floats on this arch, but we can't + -- return error because the return type is unboxed... + RcFloat + -> case rr of + RealRegSingle regNo + | regNo < 16 -> _ILIT(0) + | otherwise -> _ILIT(0) + + RealRegPair{} -> _ILIT(0) + + RcDouble + -> case rr of + RealRegSingle regNo + | regNo < 16 -> _ILIT(0) + | otherwise -> _ILIT(1) + + RealRegPair{} -> _ILIT(0) +#else +realRegSqueeze _ _ = _ILIT(0) +#endif -mkVReg :: Unique -> Size -> Reg -mkVReg u size - | not (isFloatSize size) = VirtualRegI u - | otherwise - = case size of - FF32 -> VirtualRegD u - FF64 -> VirtualRegD u - _ -> panic "mkVReg" -- ----------------------------------------------------------------------------- @@ -253,38 +277,6 @@ argRegs _ = panic "MachRegs.argRegs(x86): should not be used!" --- -allArgRegs :: [Reg] - -#if i386_TARGET_ARCH -allArgRegs = panic "X86.Regs.allArgRegs: should not be used!" - -#elif x86_64_TARGET_ARCH -allArgRegs = map RealReg [rdi,rsi,rdx,rcx,r8,r9] - -#else -allArgRegs = panic "X86.Regs.allArgRegs: not defined for this architecture" -#endif - - --- | these are the regs which we cannot assume stay alive over a C call. -callClobberedRegs :: [Reg] - -#if i386_TARGET_ARCH --- caller-saves registers -callClobberedRegs - = map RealReg [eax,ecx,edx,fake0,fake1,fake2,fake3,fake4,fake5] - -#elif x86_64_TARGET_ARCH --- all xmm regs are caller-saves --- caller-saves registers -callClobberedRegs - = map RealReg ([rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11] ++ [16..31]) - -#else -callClobberedRegs - = panic "X86.Regs.callClobberedRegs: not defined for this architecture" -#endif -- | The complete set of machine registers. @@ -303,35 +295,31 @@ allMachRegNos = panic "X86.Regs.callClobberedRegs: not defined for this architec -- | Take the class of a register. -{-# INLINE regClass #-} -regClass :: Reg -> RegClass +{-# INLINE classOfRealReg #-} +classOfRealReg :: RealReg -> RegClass #if i386_TARGET_ARCH -- On x86, we might want to have an 8-bit RegClass, which would -- contain just regs 1-4 (the others don't have 8-bit versions). -- However, we can get away without this at the moment because the -- only allocatable integer regs are also 8-bit compatible (1, 3, 4). -regClass (RealReg i) = if i < 8 then RcInteger else RcDouble -regClass (VirtualRegI u) = RcInteger -regClass (VirtualRegHi u) = RcInteger -regClass (VirtualRegD u) = RcDouble -regClass (VirtualRegF u) = pprPanic "regClass(x86):VirtualRegF" - (ppr (VirtualRegF u)) +classOfRealReg reg + = case reg of + RealRegSingle i -> if i < 8 then RcInteger else RcDouble + RealRegPair{} -> panic "X86.Regs.classOfRealReg: RegPairs on this arch" #elif x86_64_TARGET_ARCH -- On x86, we might want to have an 8-bit RegClass, which would -- contain just regs 1-4 (the others don't have 8-bit versions). -- However, we can get away without this at the moment because the -- only allocatable integer regs are also 8-bit compatible (1, 3, 4). -regClass (RealReg i) = if i < 16 then RcInteger else RcDouble -regClass (VirtualRegI u) = RcInteger -regClass (VirtualRegHi u) = RcInteger -regClass (VirtualRegD u) = RcDouble -regClass (VirtualRegF u) = pprPanic "regClass(x86_64):VirtualRegF" - (ppr (VirtualRegF u)) +classOfRealReg reg + = case reg of + RealRegSingle i -> if i < 16 then RcInteger else RcDouble + RealRegPair{} -> panic "X86.Regs.classOfRealReg: RegPairs on this arch" #else -regClass _ = panic "X86.Regs.regClass: not defined for this architecture" +classOfRealReg _ = panic "X86.Regs.regClass: not defined for this architecture" #endif @@ -345,6 +333,7 @@ showReg n then regNames !! n else "%unknown_x86_real_reg_" ++ show n +regNames :: [String] regNames = ["%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp", "%fake0", "%fake1", "%fake2", "%fake3", "%fake4", "%fake5", "%fake6"] @@ -355,6 +344,7 @@ showReg n | n >= 8 = "%r" ++ show n | otherwise = regNames !! n +regNames :: [String] regNames = ["%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%rbp", "%rsp" ] @@ -384,25 +374,24 @@ regs. @regClass@ barfs if you give it a VirtualRegF, and mkVReg above should never generate them. -} -#if i386_TARGET_ARCH fake0, fake1, fake2, fake3, fake4, fake5, eax, ebx, ecx, edx, esp, ebp, esi, edi :: Reg -eax = RealReg 0 -ebx = RealReg 1 -ecx = RealReg 2 -edx = RealReg 3 -esi = RealReg 4 -edi = RealReg 5 -ebp = RealReg 6 -esp = RealReg 7 -fake0 = RealReg 8 -fake1 = RealReg 9 -fake2 = RealReg 10 -fake3 = RealReg 11 -fake4 = RealReg 12 -fake5 = RealReg 13 -#endif +eax = regSingle 0 +ebx = regSingle 1 +ecx = regSingle 2 +edx = regSingle 3 +esi = regSingle 4 +edi = regSingle 5 +ebp = regSingle 6 +esp = regSingle 7 +fake0 = regSingle 8 +fake1 = regSingle 9 +fake2 = regSingle 10 +fake3 = regSingle 11 +fake4 = regSingle 12 +fake5 = regSingle 13 + {- @@ -413,52 +402,53 @@ AMD x86_64 architecture: -} -#if x86_64_TARGET_ARCH -allFPArgRegs :: [Reg] -allFPArgRegs = map RealReg [xmm0 .. xmm7] - -ripRel imm = AddrBaseIndex EABaseRip EAIndexNone imm - - rax, rbx, rcx, rdx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 :: Reg -rax = RealReg 0 -rbx = RealReg 1 -rcx = RealReg 2 -rdx = RealReg 3 -rsi = RealReg 4 -rdi = RealReg 5 -rbp = RealReg 6 -rsp = RealReg 7 -r8 = RealReg 8 -r9 = RealReg 9 -r10 = RealReg 10 -r11 = RealReg 11 -r12 = RealReg 12 -r13 = RealReg 13 -r14 = RealReg 14 -r15 = RealReg 15 -xmm0 = RealReg 16 -xmm1 = RealReg 17 -xmm2 = RealReg 18 -xmm3 = RealReg 19 -xmm4 = RealReg 20 -xmm5 = RealReg 21 -xmm6 = RealReg 22 -xmm7 = RealReg 23 -xmm8 = RealReg 24 -xmm9 = RealReg 25 -xmm10 = RealReg 26 -xmm11 = RealReg 27 -xmm12 = RealReg 28 -xmm13 = RealReg 29 -xmm14 = RealReg 30 -xmm15 = RealReg 31 +rax = regSingle 0 +rbx = regSingle 1 +rcx = regSingle 2 +rdx = regSingle 3 +rsi = regSingle 4 +rdi = regSingle 5 +rbp = regSingle 6 +rsp = regSingle 7 +r8 = regSingle 8 +r9 = regSingle 9 +r10 = regSingle 10 +r11 = regSingle 11 +r12 = regSingle 12 +r13 = regSingle 13 +r14 = regSingle 14 +r15 = regSingle 15 +xmm0 = regSingle 16 +xmm1 = regSingle 17 +xmm2 = regSingle 18 +xmm3 = regSingle 19 +xmm4 = regSingle 20 +xmm5 = regSingle 21 +xmm6 = regSingle 22 +xmm7 = regSingle 23 +xmm8 = regSingle 24 +xmm9 = regSingle 25 +xmm10 = regSingle 26 +xmm11 = regSingle 27 +xmm12 = regSingle 28 +xmm13 = regSingle 29 +xmm14 = regSingle 30 +xmm15 = regSingle 31 + +allFPArgRegs :: [Reg] +allFPArgRegs = map regSingle [16 .. 23] + +ripRel :: Displacement -> AddrMode +ripRel imm = AddrBaseIndex EABaseRip EAIndexNone imm + -- so we can re-use some x86 code: +{- eax = rax ebx = rbx ecx = rcx @@ -467,16 +457,19 @@ esi = rsi edi = rdi ebp = rbp esp = rsp +-} -xmm n = RealReg (16+n) +xmm :: RegNo -> Reg +xmm n = regSingle (16+n) -#endif -- horror show ----------------------------------------------------------------- -freeReg :: RegNo -> FastBool -globalRegMaybe :: GlobalReg -> Maybe Reg +freeReg :: RegNo -> FastBool +globalRegMaybe :: GlobalReg -> Maybe RealReg +allArgRegs :: [Reg] +callClobberedRegs :: [Reg] #if defined(i386_TARGET_ARCH) || defined(x86_64_TARGET_ARCH) @@ -602,7 +595,7 @@ freeReg REG_Hp = fastBool False #ifdef REG_HpLim freeReg REG_HpLim = fastBool False #endif -freeReg n = fastBool True +freeReg _ = fastBool True -- | Returns 'Nothing' if this global register is not stored @@ -610,85 +603,146 @@ freeReg n = fastBool True -- reg is the machine register it is stored in. #ifdef REG_Base -globalRegMaybe BaseReg = Just (RealReg REG_Base) +globalRegMaybe BaseReg = Just (RealRegSingle REG_Base) #endif #ifdef REG_R1 -globalRegMaybe (VanillaReg 1 _) = Just (RealReg REG_R1) +globalRegMaybe (VanillaReg 1 _) = Just (RealRegSingle REG_R1) #endif #ifdef REG_R2 -globalRegMaybe (VanillaReg 2 _) = Just (RealReg REG_R2) +globalRegMaybe (VanillaReg 2 _) = Just (RealRegSingle REG_R2) #endif #ifdef REG_R3 -globalRegMaybe (VanillaReg 3 _) = Just (RealReg REG_R3) +globalRegMaybe (VanillaReg 3 _) = Just (RealRegSingle REG_R3) #endif #ifdef REG_R4 -globalRegMaybe (VanillaReg 4 _) = Just (RealReg REG_R4) +globalRegMaybe (VanillaReg 4 _) = Just (RealRegSingle REG_R4) #endif #ifdef REG_R5 -globalRegMaybe (VanillaReg 5 _) = Just (RealReg REG_R5) +globalRegMaybe (VanillaReg 5 _) = Just (RealRegSingle REG_R5) #endif #ifdef REG_R6 -globalRegMaybe (VanillaReg 6 _) = Just (RealReg REG_R6) +globalRegMaybe (VanillaReg 6 _) = Just (RealRegSingle REG_R6) #endif #ifdef REG_R7 -globalRegMaybe (VanillaReg 7 _) = Just (RealReg REG_R7) +globalRegMaybe (VanillaReg 7 _) = Just (RealRegSingle REG_R7) #endif #ifdef REG_R8 -globalRegMaybe (VanillaReg 8 _) = Just (RealReg REG_R8) +globalRegMaybe (VanillaReg 8 _) = Just (RealRegSingle REG_R8) #endif #ifdef REG_R9 -globalRegMaybe (VanillaReg 9 _) = Just (RealReg REG_R9) +globalRegMaybe (VanillaReg 9 _) = Just (RealRegSingle REG_R9) #endif #ifdef REG_R10 -globalRegMaybe (VanillaReg 10 _) = Just (RealReg REG_R10) +globalRegMaybe (VanillaReg 10 _) = Just (RealRegSingle REG_R10) #endif #ifdef REG_F1 -globalRegMaybe (FloatReg 1) = Just (RealReg REG_F1) +globalRegMaybe (FloatReg 1) = Just (RealRegSingle REG_F1) #endif #ifdef REG_F2 -globalRegMaybe (FloatReg 2) = Just (RealReg REG_F2) +globalRegMaybe (FloatReg 2) = Just (RealRegSingle REG_F2) #endif #ifdef REG_F3 -globalRegMaybe (FloatReg 3) = Just (RealReg REG_F3) +globalRegMaybe (FloatReg 3) = Just (RealRegSingle REG_F3) #endif #ifdef REG_F4 -globalRegMaybe (FloatReg 4) = Just (RealReg REG_F4) +globalRegMaybe (FloatReg 4) = Just (RealRegSingle REG_F4) #endif #ifdef REG_D1 -globalRegMaybe (DoubleReg 1) = Just (RealReg REG_D1) +globalRegMaybe (DoubleReg 1) = Just (RealRegSingle REG_D1) #endif #ifdef REG_D2 -globalRegMaybe (DoubleReg 2) = Just (RealReg REG_D2) +globalRegMaybe (DoubleReg 2) = Just (RealRegSingle REG_D2) #endif #ifdef REG_Sp -globalRegMaybe Sp = Just (RealReg REG_Sp) +globalRegMaybe Sp = Just (RealRegSingle REG_Sp) #endif #ifdef REG_Lng1 -globalRegMaybe (LongReg 1) = Just (RealReg REG_Lng1) +globalRegMaybe (LongReg 1) = Just (RealRegSingle REG_Lng1) #endif #ifdef REG_Lng2 -globalRegMaybe (LongReg 2) = Just (RealReg REG_Lng2) +globalRegMaybe (LongReg 2) = Just (RealRegSingle REG_Lng2) #endif #ifdef REG_SpLim -globalRegMaybe SpLim = Just (RealReg REG_SpLim) +globalRegMaybe SpLim = Just (RealRegSingle REG_SpLim) #endif #ifdef REG_Hp -globalRegMaybe Hp = Just (RealReg REG_Hp) +globalRegMaybe Hp = Just (RealRegSingle REG_Hp) #endif #ifdef REG_HpLim -globalRegMaybe HpLim = Just (RealReg REG_HpLim) +globalRegMaybe HpLim = Just (RealRegSingle REG_HpLim) #endif #ifdef REG_CurrentTSO -globalRegMaybe CurrentTSO = Just (RealReg REG_CurrentTSO) +globalRegMaybe CurrentTSO = Just (RealRegSingle REG_CurrentTSO) #endif #ifdef REG_CurrentNursery -globalRegMaybe CurrentNursery = Just (RealReg REG_CurrentNursery) +globalRegMaybe CurrentNursery = Just (RealRegSingle REG_CurrentNursery) #endif globalRegMaybe _ = Nothing +-- + +#if i386_TARGET_ARCH +allArgRegs = panic "X86.Regs.allArgRegs: should not be used!" + +#elif x86_64_TARGET_ARCH +allArgRegs = map regSingle [rdi,rsi,rdx,rcx,r8,r9] + +#else +allArgRegs = panic "X86.Regs.allArgRegs: not defined for this architecture" +#endif + + +-- | these are the regs which we cannot assume stay alive over a C call. + +#if i386_TARGET_ARCH +-- caller-saves registers +callClobberedRegs + = map regSingle [eax,ecx,edx,fake0,fake1,fake2,fake3,fake4,fake5] + +#elif x86_64_TARGET_ARCH +-- all xmm regs are caller-saves +-- caller-saves registers +callClobberedRegs + = map regSingle ([rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11] ++ [16..31]) + +#else +callClobberedRegs + = panic "X86.Regs.callClobberedRegs: not defined for this architecture" +#endif + #else /* i386_TARGET_ARCH || x86_64_TARGET_ARCH */ + + freeReg _ = 0# globalRegMaybe _ = panic "X86.Regs.globalRegMaybe: not defined" +allArgRegs = panic "X86.Regs.globalRegMaybe: not defined" +callClobberedRegs = panic "X86.Regs.globalRegMaybe: not defined" + + #endif + +-- We map STG registers onto appropriate CmmExprs. Either they map +-- to real machine registers or stored as offsets from BaseReg. Given +-- a GlobalReg, get_GlobalReg_reg_or_addr produces either the real +-- register it is in, on this platform, or a CmmExpr denoting the +-- address in the register table holding it. +-- (See also get_GlobalReg_addr in CgUtils.) + +get_GlobalReg_reg_or_addr :: GlobalReg -> Either RealReg CmmExpr +get_GlobalReg_reg_or_addr mid + = case globalRegMaybe mid of + Just rr -> Left rr + Nothing -> Right (get_GlobalReg_addr mid) + + +-- allocatableRegs is allMachRegNos with the fixed-use regs removed. +-- i.e., these are the regs for which we are prepared to allow the +-- register allocator to attempt to map VRegs to. +allocatableRegs :: [RealReg] +allocatableRegs + = let isFree i = isFastTrue (freeReg i) + in map RealRegSingle $ filter isFree allMachRegNos + +