Commit cfd08a99 authored by rwbarton's avatar rwbarton

Add MO_AddIntC, MO_SubIntC MachOps and implement in X86 backend

Summary:
These MachOps are used by addIntC# and subIntC#, which in turn are
used in integer-gmp when adding or subtracting small Integers. The
following benchmark shows a ~6% speedup after this commit on x86_64
(building GHC with BuildFlavour=perf).

    {-# LANGUAGE MagicHash #-}

    import GHC.Exts
    import Criterion.Main

    count :: Int -> Integer
    count (I# n#) = go n# 0
      where go :: Int# -> Integer -> Integer
            go 0# acc = acc
            go n# acc = go (n# -# 1#) $! acc + 1

    main = defaultMain [bgroup "count"
                          [bench "100" $ whnf count 100]]

Differential Revision: https://phabricator.haskell.org/D140
parent 104a66a4
......@@ -526,6 +526,8 @@ data CallishMachOp
| MO_U_QuotRem Width
| MO_U_QuotRem2 Width
| MO_Add2 Width
| MO_AddIntC Width
| MO_SubIntC Width
| MO_U_Mul2 Width
| MO_WriteBarrier
......
......@@ -765,6 +765,8 @@ pprCallishMachOp_for_C mop
MO_U_QuotRem {} -> unsupported
MO_U_QuotRem2 {} -> unsupported
MO_Add2 {} -> unsupported
MO_AddIntC {} -> unsupported
MO_SubIntC {} -> unsupported
MO_U_Mul2 {} -> unsupported
MO_Touch -> unsupported
(MO_Prefetch_Data _ ) -> unsupported
......
......@@ -806,9 +806,11 @@ callishPrimOpSupported dflags op
WordAdd2Op | ncg && x86ish -> Left (MO_Add2 (wordWidth dflags))
| otherwise -> Right genericWordAdd2Op
IntAddCOp -> Right genericIntAddCOp
IntAddCOp | ncg && x86ish -> Left (MO_AddIntC (wordWidth dflags))
| otherwise -> Right genericIntAddCOp
IntSubCOp -> Right genericIntSubCOp
IntSubCOp | ncg && x86ish -> Left (MO_SubIntC (wordWidth dflags))
| otherwise -> Right genericIntSubCOp
WordMul2Op | ncg && x86ish -> Left (MO_U_Mul2 (wordWidth dflags))
| otherwise -> Right genericWordMul2Op
......
......@@ -572,6 +572,8 @@ cmmPrimOpFunctions mop = do
MO_U_QuotRem {} -> unsupported
MO_U_QuotRem2 {} -> unsupported
MO_Add2 {} -> unsupported
MO_AddIntC {} -> unsupported
MO_SubIntC {} -> unsupported
MO_U_Mul2 {} -> unsupported
MO_WriteBarrier -> unsupported
MO_Touch -> unsupported
......
......@@ -1162,6 +1162,8 @@ genCCall' dflags gcp target dest_regs args0
MO_U_QuotRem {} -> unsupported
MO_U_QuotRem2 {} -> unsupported
MO_Add2 {} -> unsupported
MO_AddIntC {} -> unsupported
MO_SubIntC {} -> unsupported
MO_U_Mul2 {} -> unsupported
MO_WriteBarrier -> unsupported
MO_Touch -> unsupported
......
......@@ -665,6 +665,8 @@ outOfLineMachOp_table mop
MO_U_QuotRem {} -> unsupported
MO_U_QuotRem2 {} -> unsupported
MO_Add2 {} -> unsupported
MO_AddIntC {} -> unsupported
MO_SubIntC {} -> unsupported
MO_U_Mul2 {} -> unsupported
MO_WriteBarrier -> unsupported
MO_Touch -> unsupported
......
......@@ -1989,6 +1989,10 @@ genCCall _ is32Bit target dest_regs args = do
ADC size (OpImm (ImmInteger 0)) (OpReg reg_h)
return code
_ -> panic "genCCall: Wrong number of arguments/results for add2"
(PrimTarget (MO_AddIntC width), [res_r, res_c]) ->
addSubIntC platform ADD_CC (Just . ADD_CC) width res_r res_c args
(PrimTarget (MO_SubIntC width), [res_r, res_c]) ->
addSubIntC platform SUB_CC (const Nothing) width res_r res_c args
(PrimTarget (MO_U_Mul2 width), [res_h, res_l]) ->
case args of
[arg_x, arg_y] ->
......@@ -2042,6 +2046,20 @@ genCCall _ is32Bit target dest_regs args = do
divOp _ _ _ _ _ _ _
= panic "genCCall: Wrong number of results for divOp"
addSubIntC platform instr mrevinstr width res_r res_c [arg_x, arg_y]
= do let size = intSize width
rCode <- anyReg =<< trivialCode width (instr size)
(mrevinstr size) arg_x arg_y
reg_tmp <- getNewRegNat II8
let reg_c = getRegisterReg platform True (CmmLocal res_c)
reg_r = getRegisterReg platform True (CmmLocal res_r)
code = rCode reg_r `snocOL`
SETCC OFLO (OpReg reg_tmp) `snocOL`
MOVZxL II8 (OpReg reg_tmp) (OpReg reg_c)
return code
addSubIntC _ _ _ _ _ _ _
= panic "genCCall: Wrong number of arguments/results for addSubIntC"
genCCall32' :: DynFlags
-> ForeignTarget -- function to call
-> [CmmFormal] -- where to put the result
......@@ -2480,6 +2498,8 @@ outOfLineCmmOp mop res args
MO_U_QuotRem {} -> unsupported
MO_U_QuotRem2 {} -> unsupported
MO_Add2 {} -> unsupported
MO_AddIntC {} -> unsupported
MO_SubIntC {} -> unsupported
MO_U_Mul2 {} -> unsupported
MO_WriteBarrier -> unsupported
MO_Touch -> unsupported
......
......@@ -210,6 +210,7 @@ data Instr
-- Do not rewrite these instructions to "equivalent" ones that
-- have different effect on the condition register! (See #9013.)
| ADD_CC Size Operand Operand
| SUB_CC Size Operand Operand
-- Simple bit-twiddling.
| AND Size Operand Operand
......@@ -371,6 +372,7 @@ x86_regUsageOfInstr platform instr
DIV _ op -> mkRU (eax:edx:use_R op []) [eax,edx]
IDIV _ op -> mkRU (eax:edx:use_R op []) [eax,edx]
ADD_CC _ src dst -> usageRM src dst
SUB_CC _ src dst -> usageRM src dst
AND _ src dst -> usageRM src dst
OR _ src dst -> usageRM src dst
......@@ -548,6 +550,7 @@ x86_patchRegsOfInstr instr env
IDIV sz op -> patch1 (IDIV sz) op
DIV sz op -> patch1 (DIV sz) op
ADD_CC sz src dst -> patch2 (ADD_CC sz) src dst
SUB_CC sz src dst -> patch2 (SUB_CC sz) src dst
AND sz src dst -> patch2 (AND sz) src dst
OR sz src dst -> patch2 (OR sz) src dst
XOR sz src dst -> patch2 (XOR sz) src dst
......
......@@ -568,6 +568,8 @@ pprInstr (IMUL size op1 op2) = pprSizeOpOp (sLit "imul") size op1 op2
pprInstr (ADD_CC size src dst)
= pprSizeOpOp (sLit "add") size src dst
pprInstr (SUB_CC size src dst)
= pprSizeOpOp (sLit "sub") size src dst
{- A hack. The Intel documentation says that "The two and three
operand forms [of IMUL] may also be used with unsigned operands
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment