Ticket #5598: 0001-Implement-quotRemInt-primop.patch

File 0001-Implement-quotRemInt-primop.patch, 15.3 KB (added by igloo, 16 months ago)
  • compiler/cmm/CmmLint.hs

    From c9b69847ef7559bdabd9b75962111605bd357dc2 Mon Sep 17 00:00:00 2001
    From: Ian Lynagh <igloo@earth.li>
    Date: Sun, 29 Jan 2012 21:25:55 +0000
    Subject: [PATCH] Implement quotRemInt# primop
    
    This means we can do quotRem with only a single division instruction,
    rather than both quot and rem doing duplicate divisions.
    ---
     compiler/cmm/CmmLint.hs                 |    8 +++++
     compiler/cmm/CmmMachOp.hs               |    3 ++
     compiler/cmm/CmmOpt.hs                  |    1 +
     compiler/cmm/CmmType.hs                 |   15 +++++++++-
     compiler/cmm/OldCmm.hs                  |    2 +
     compiler/cmm/OldPprCmm.hs               |    3 ++
     compiler/cmm/PprC.hs                    |    5 +++
     compiler/codeGen/CgPrimOp.hs            |    5 +++
     compiler/llvmGen/LlvmCodeGen/CodeGen.hs |    5 +++
     compiler/nativeGen/PPC/CodeGen.hs       |    2 +
     compiler/nativeGen/SPARC/CodeGen.hs     |    2 +
     compiler/nativeGen/X86/CodeGen.hs       |   47 +++++++++++++++++++++++++++++++
     compiler/prelude/primops.txt.pp         |    5 +++
     13 files changed, 102 insertions(+), 1 deletions(-)
    
    diff --git a/compiler/cmm/CmmLint.hs b/compiler/cmm/CmmLint.hs
    index bed3b18..13f7429 100644
    a b  
    129129            if (erep `cmmEqType_ignoring_ptrhood` reg_ty) 
    130130                then return () 
    131131                else cmmLintAssignErr platform stmt erep reg_ty 
     132          lint stmt@(CmmAssign2 reg1 reg2 expr) = do 
     133            erep <- lintCmmExpr platform expr 
     134            let reg1_ty = cmmRegType reg1 
     135                reg2_ty = cmmRegType reg2 
     136                reg_tys = cmmTypes [reg1_ty, reg2_ty] 
     137            if (erep `cmmEqType_ignoring_ptrhood` reg_tys) 
     138                then return () 
     139                else cmmLintAssignErr platform stmt erep reg_tys 
    132140          lint (CmmStore l r) = do 
    133141            _ <- lintCmmExpr platform l 
    134142            _ <- lintCmmExpr platform r 
  • compiler/cmm/CmmMachOp.hs

    diff --git a/compiler/cmm/CmmMachOp.hs b/compiler/cmm/CmmMachOp.hs
    index 2effa3a..2aba6f3 100644
    a b  
    5151  | MO_S_MulMayOflo Width       -- nonzero if signed multiply overflows 
    5252  | MO_S_Quot Width             -- signed / (same semantics as IntQuotOp) 
    5353  | MO_S_Rem  Width             -- signed % (same semantics as IntRemOp) 
     54  | MO_S_QuotRem Width -- signed / % (same semantics as IntQuotOp and IntRemOp) 
    5455  | MO_S_Neg  Width             -- unary - 
    5556 
    5657  -- Unsigned multiply/divide 
     
    295296    MO_S_MulMayOflo r   -> cmmBits r 
    296297    MO_S_Quot r         -> cmmBits r 
    297298    MO_S_Rem  r         -> cmmBits r 
     299    MO_S_QuotRem r      -> cmmTypes [cmmBits r, cmmBits r] 
    298300    MO_S_Neg  r         -> cmmBits r 
    299301    MO_U_MulMayOflo r   -> cmmBits r 
    300302    MO_U_Quot r         -> cmmBits r 
     
    363365    MO_S_MulMayOflo r   -> [r,r] 
    364366    MO_S_Quot r         -> [r,r] 
    365367    MO_S_Rem  r         -> [r,r] 
     368    MO_S_QuotRem  r     -> [r,r] 
    366369    MO_S_Neg  r         -> [r] 
    367370    MO_U_MulMayOflo r   -> [r,r] 
    368371    MO_U_Quot r         -> [r,r] 
  • compiler/cmm/CmmOpt.hs

    diff --git a/compiler/cmm/CmmOpt.hs b/compiler/cmm/CmmOpt.hs
    index ae715a9..e9ce2bb 100644
    a b  
    5858                stmt m CmmNop = m 
    5959                stmt m (CmmComment _) = m 
    6060                stmt m (CmmAssign _ e) = expr m e 
     61                stmt m (CmmAssign2 _ _ e) = expr m e 
    6162                stmt m (CmmStore e1 e2) = expr (expr m e1) e2 
    6263                stmt m (CmmCall c _ as _) = f (actuals m as) c 
    6364                    where f m (CmmCallee e _) = expr m e 
  • compiler/cmm/CmmType.hs

    diff --git a/compiler/cmm/CmmType.hs b/compiler/cmm/CmmType.hs
    index 2727754..28afeae 100644
    a b  
    33    ( CmmType   -- Abstract 
    44    , b8, b16, b32, b64, f32, f64, bWord, bHalfWord, gcWord 
    55    , cInt, cLong 
    6     , cmmBits, cmmFloat 
     6    , cmmTypes, cmmBits, cmmFloat 
    77    , typeWidth, cmmEqType, cmmEqType_ignoring_ptrhood 
    88    , isFloatType, isGcPtrType, isWord32, isWord64, isFloat64, isFloat32 
    99 
     
    3535 
    3636data CmmType    -- The important one! 
    3737  = CmmType CmmCat Width 
     38  | CmmTypes [CmmType] 
    3839 
    3940data CmmCat     -- "Category" (not exported) 
    4041   = GcPtrCat   -- GC pointer 
     
    4546 
    4647instance Outputable CmmType where 
    4748  ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid) 
     49  ppr (CmmTypes ts) = parens (ptext (sLit "CmmTypes") <+> sep (map ppr ts)) 
    4850 
    4951instance Outputable CmmCat where 
    5052  ppr FloatCat  = ptext $ sLit("F") 
     
    6365-- So we use an explicit function to force you to think about it 
    6466cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality 
    6567cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2 
     68cmmEqType (CmmTypes ts1) (CmmTypes ts2) = and $ zipWith cmmEqType ts1 ts2 
     69cmmEqType (CmmType {}) (CmmTypes {}) = False 
     70cmmEqType (CmmTypes {}) (CmmType {}) = False 
    6671 
    6772cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool 
    6873  -- This equality is temporary; used in CmmLint 
     
    7479      FloatCat `weak_eq` _other   = False 
    7580      _other   `weak_eq` FloatCat = False 
    7681      _word1   `weak_eq` _word2   = True        -- Ignores GcPtr 
     82cmmEqType_ignoring_ptrhood (CmmTypes ts1) (CmmTypes ts2) 
     83    = and $ zipWith cmmEqType_ignoring_ptrhood ts1 ts2 
     84cmmEqType_ignoring_ptrhood (CmmType {}) (CmmTypes {}) = False 
     85cmmEqType_ignoring_ptrhood (CmmTypes {}) (CmmType {}) = False 
    7786 
    7887--- Simple operations on CmmType ----- 
    7988typeWidth :: CmmType -> Width 
    8089typeWidth (CmmType _ w) = w 
     90typeWidth _ = panic "XXX typeWidth" 
     91 
     92cmmTypes :: [CmmType] -> CmmType 
     93cmmTypes = CmmTypes 
    8194 
    8295cmmBits, cmmFloat :: Width -> CmmType 
    8396cmmBits  = CmmType BitsCat 
  • compiler/cmm/OldCmm.hs

    diff --git a/compiler/cmm/OldCmm.hs b/compiler/cmm/OldCmm.hs
    index 7b5917d..2c6460a 100644
    a b  
    147147  | CmmComment FastString 
    148148 
    149149  | CmmAssign CmmReg CmmExpr      -- Assign to register 
     150  | CmmAssign2 CmmReg CmmReg CmmExpr      -- Assign to 2 registers 
    150151 
    151152  | CmmStore CmmExpr CmmExpr      -- Assign to memory location. Size is 
    152153                                  -- given by cmmExprType of the rhs. 
     
    210211      stmt (CmmNop)                  = id 
    211212      stmt (CmmComment {})           = id 
    212213      stmt (CmmAssign _ e)           = gen e 
     214      stmt (CmmAssign2 _ _ e)        = gen e 
    213215      stmt (CmmStore e1 e2)          = gen e1 . gen e2 
    214216      stmt (CmmCall target _ es _)   = gen target . gen es 
    215217      stmt (CmmBranch _)             = id 
  • compiler/cmm/OldPprCmm.hs

    diff --git a/compiler/cmm/OldPprCmm.hs b/compiler/cmm/OldPprCmm.hs
    index 4b1da0b..e63ba44 100644
    a b  
    113113    -- reg = expr; 
    114114    CmmAssign reg expr -> ppr reg <+> equals <+> pprPlatform platform expr <> semi 
    115115 
     116    -- reg1, reg2 = expr; 
     117    CmmAssign2 reg1 reg2 expr -> ppr reg1 <> comma <+> ppr reg2 <+> equals <+> pprPlatform platform expr <> semi 
     118 
    116119    -- rep[lv] = expr; 
    117120    CmmStore lv expr -> rep <> brackets(pprPlatform platform lv) <+> equals <+> pprPlatform platform expr <> semi 
    118121        where 
  • compiler/cmm/PprC.hs

    diff --git a/compiler/cmm/PprC.hs b/compiler/cmm/PprC.hs
    index 658e3ca..1b8b28c 100644
    a b  
    181181                          -- large. 
    182182 
    183183    CmmAssign dest src -> pprAssign platform dest src 
     184    CmmAssign2 dest1 dest2 src -> pprAssign2 platform dest1 dest2 src 
    184185 
    185186    CmmStore  dest src 
    186187        | typeWidth rep == W64 && wordWidth /= W64 
     
    527528 
    528529        MO_S_Quot       _ -> char '/' 
    529530        MO_S_Rem        _ -> char '%' 
     531        MO_S_QuotRem    _ -> panic "XXX pprMachOp_for_C" 
    530532        MO_S_Neg        _ -> char '-' 
    531533 
    532534        MO_U_Quot       _ -> char '/' 
     
    717719                       then ptext (sLit "ASSIGN_BaseReg") <> parens x <> semi 
    718720                       else pprReg r1 <> ptext (sLit " = ") <> x <> semi 
    719721 
     722pprAssign2 :: Platform -> CmmReg -> CmmReg -> CmmExpr -> SDoc 
     723pprAssign2 = panic "XXX pprAssign2" 
     724 
    720725-- --------------------------------------------------------------------- 
    721726-- Registers 
    722727 
  • compiler/codeGen/CgPrimOp.hs

    diff --git a/compiler/codeGen/CgPrimOp.hs b/compiler/codeGen/CgPrimOp.hs
    index b0865d6..942bb50 100644
    a b  
    440440   = let stmt = CmmAssign (CmmLocal res) (CmmMachOp mop args) in 
    441441     stmtC stmt 
    442442 
     443emitPrimOp [res_q, res_r] IntQuotRemOp args _ 
     444    = let stmt = CmmAssign2 (CmmLocal res_q) (CmmLocal res_r) 
     445                            (CmmMachOp (MO_S_QuotRem wordWidth) args) 
     446      in stmtC stmt 
     447 
    443448emitPrimOp _ op _ _ 
    444449 = pprPanic "emitPrimOp: can't translate PrimOp" (ppr op) 
    445450 
  • compiler/llvmGen/LlvmCodeGen/CodeGen.hs

    diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
    index d503782..32090d1 100644
    a b  
    117117    CmmComment _         -> return (env, nilOL, []) -- nuke comments 
    118118 
    119119    CmmAssign reg src    -> genAssign env reg src 
     120    CmmAssign2 _ _ _     -> panic "XXX stmtToInstrs" 
    120121    CmmStore addr src    -> genStore env addr src 
    121122 
    122123    CmmBranch id         -> genBranch env id 
     
    458459 
    459460    (MO_PopCnt w) -> fsLit $ "llvm.ctpop."  ++ show (widthToLlvmInt w) 
    460461 
     462    -- MO_S_QuotRem _ -> panic "XXX LLVM MO_S_QuotRem" 
     463 
    461464    MO_WriteBarrier -> 
    462465        panic $ "cmmPrimOpFunctions: MO_WriteBarrier not supported here" 
    463466    MO_Touch -> 
     
    766769    MO_S_MulMayOflo _ -> panicOp 
    767770    MO_S_Quot _       -> panicOp 
    768771    MO_S_Rem _        -> panicOp 
     772    MO_S_QuotRem _    -> panic "XXX genMachOp" 
    769773    MO_U_MulMayOflo _ -> panicOp 
    770774    MO_U_Quot _       -> panicOp 
    771775    MO_U_Rem _        -> panicOp 
     
    886890 
    887891    MO_S_Quot _ -> genBinMach LM_MO_SDiv 
    888892    MO_S_Rem  _ -> genBinMach LM_MO_SRem 
     893    MO_S_QuotRem _ -> panic "XXX genMachOp_slow" 
    889894 
    890895    MO_U_Quot _ -> genBinMach LM_MO_UDiv 
    891896    MO_U_Rem  _ -> genBinMach LM_MO_URem 
  • compiler/nativeGen/PPC/CodeGen.hs

    diff --git a/compiler/nativeGen/PPC/CodeGen.hs b/compiler/nativeGen/PPC/CodeGen.hs
    index 7b704cb..490537f 100644
    a b  
    127127        where ty = cmmRegType reg 
    128128              size = cmmTypeSize ty 
    129129 
     130    CmmAssign2 _ _ _ -> panic "XXX PPC stmtToInstrs" 
     131 
    130132    CmmStore addr src 
    131133      | isFloatType ty -> assignMem_FltCode size addr src 
    132134      | target32Bit (targetPlatform dflags) && 
  • compiler/nativeGen/SPARC/CodeGen.hs

    diff --git a/compiler/nativeGen/SPARC/CodeGen.hs b/compiler/nativeGen/SPARC/CodeGen.hs
    index 4c295f1..1c0effd 100644
    a b  
    128128        where ty = cmmRegType reg 
    129129              size = cmmTypeSize ty 
    130130 
     131    CmmAssign2 _ _ _ -> panic "XXX SPARC stmtToInstrs" 
     132 
    131133    CmmStore addr src 
    132134      | isFloatType ty  -> assignMem_FltCode size addr src 
    133135      | isWord64 ty     -> assignMem_I64Code      addr src 
  • compiler/nativeGen/X86/CodeGen.hs

    diff --git a/compiler/nativeGen/X86/CodeGen.hs b/compiler/nativeGen/X86/CodeGen.hs
    index c685195..d2d5f14 100644
    a b  
    153153        where ty = cmmRegType reg 
    154154              size = cmmTypeSize ty 
    155155 
     156    CmmAssign2 reg1 reg2 src 
     157      -- XXX Should probably mirror the CmmAssign tests 
     158      | otherwise              -> assign2Reg_IntCode reg1 reg2 src 
     159 
     160 
    156161    CmmStore addr src 
    157162      | isFloatType ty         -> assignMem_FltCode size addr src 
    158163      | is32Bit && isWord64 ty -> assignMem_I64Code      addr src 
     
    208213        = Fixed Size Reg InstrBlock 
    209214        | Any   Size (Reg -> InstrBlock) 
    210215 
     216data Register2 
     217        = Fixed2 Size Reg Reg InstrBlock 
     218        | Any2   Size (Reg -> Reg -> InstrBlock) 
     219 
    211220 
    212221swizzleRegisterRep :: Register -> Size -> Register 
    213222swizzleRegisterRep (Fixed _ reg code) size = Fixed size reg code 
     
    890899getRegister' _ other = do dflags <- getDynFlags 
    891900                          pprPanic "getRegister(x86)" (pprPlatform (targetPlatform dflags) other) 
    892901 
     902get2Register :: CmmExpr -> NatM Register2 
     903get2Register (CmmMachOp (MO_S_QuotRem rep) [x, y]) = do 
     904  div_code rep True x y 
     905 where 
     906    div_code width signed x y = do 
     907           (y_op, y_code) <- getRegOrMem y -- cannot be clobbered 
     908           x_code <- getAnyReg x 
     909           let 
     910             size = intSize width 
     911             widen | signed    = CLTD size 
     912                   | otherwise = XOR size (OpReg edx) (OpReg edx) 
     913 
     914             instr | signed    = IDIV 
     915                   | otherwise = DIV 
     916 
     917             code = y_code `appOL` 
     918                    x_code eax `appOL` 
     919                    toOL [widen, instr size y_op] 
     920 
     921           return (Fixed2 size eax edx code) 
     922get2Register _ = panic "XXX X86 get2Register" 
     923 
    893924 
    894925intLoadCode :: (Operand -> Operand -> Instr) -> CmmExpr 
    895926   -> NatM (Reg -> InstrBlock) 
     
    904935  r <- getRegister expr 
    905936  anyReg r 
    906937 
     938getAny2Reg :: CmmExpr -> NatM (Reg -> Reg -> InstrBlock) 
     939getAny2Reg expr = do 
     940  r2 <- get2Register expr 
     941  any2Reg r2 
     942 
    907943anyReg :: Register -> NatM (Reg -> InstrBlock) 
    908944anyReg (Any _ code)          = return code 
    909945anyReg (Fixed rep reg fcode) = return (\dst -> fcode `snocOL` reg2reg rep reg dst) 
    910946 
     947any2Reg :: Register2 -> NatM (Reg -> Reg -> InstrBlock) 
     948any2Reg (Any2 _ code)                = return code 
     949any2Reg (Fixed2 rep reg1 reg2 fcode) = return (\dst1 dst2 -> fcode `snocOL` reg2reg rep reg1 dst1 `snocOL` reg2reg rep reg2 dst2) 
     950 
    911951-- A bit like getSomeReg, but we want a reg that can be byte-addressed. 
    912952-- Fixed registers might not be byte-addressable, so we make sure we've 
    913953-- got a temporary, inserting an extra reg copy if necessary. 
     
    14061446  code <- getAnyReg src 
    14071447  return (code (getRegisterReg False{-no sse2-} reg)) 
    14081448 
     1449assign2Reg_IntCode :: CmmReg -> CmmReg -> CmmExpr -> NatM InstrBlock 
     1450-- dsts are regs, but src could be anything 
     1451assign2Reg_IntCode reg1 reg2 src = do 
     1452  code <- getAny2Reg src 
     1453  return (code (getRegisterReg False{-no sse2-} reg1) 
     1454               (getRegisterReg False{-no sse2-} reg2)) 
     1455 
    14091456 
    14101457-- Floating point assignment to memory 
    14111458assignMem_FltCode pk addr src = do 
  • compiler/prelude/primops.txt.pp

    diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp
    index 48dd768..183bd35 100644
    a b  
    210210   {Satisfies \texttt{(quotInt\# x y) *\# y +\# (remInt\# x y) == x}.} 
    211211   with can_fail = True 
    212212 
     213primop   IntQuotRemOp "quotRemInt#"    GenPrimOp 
     214   Int# -> Int# -> (# Int#, Int# #) 
     215   {Rounds towards zero.} 
     216   with can_fail = True 
     217 
    213218primop   IntNegOp    "negateInt#"    Monadic   Int# -> Int# 
    214219primop   IntAddCOp   "addIntC#"    GenPrimOp   Int# -> Int# -> (# Int#, Int# #) 
    215220         {Add with carry.  First member of result is (wrapped) sum;