diff options
author | Peter Trommler <ptrommler@acm.org> | 2017-04-25 18:37:16 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-04-25 18:39:50 -0400 |
commit | 89a3241f708502e8fbcfaddbbe634790ad9cd02a (patch) | |
tree | 9264c8bb53a229ea2a6a55debd0088bb88354bd2 /compiler/codeGen | |
parent | 9373994acaf1b73fe0e7cf8e03594c63cec8d235 (diff) | |
download | haskell-89a3241f708502e8fbcfaddbbe634790ad9cd02a.tar.gz |
PPC NCG: Implement callish prim ops
Provide PowerPC optimised implementations of callish prim ops.
MO_?_QuotRem
The generic implementation of quotient remainder prim ops uses
a division and a remainder operation. There is no remainder on
PowerPC and so we need to implement remainder "by hand" which
results in a duplication of the divide operation when using the
generic code.
Avoid this duplication by implementing the prim op in the native
code generator.
MO_U_Mul2
Use PowerPC's instructions for long multiplication.
Addition and subtraction
Use PowerPC add/subtract with carry/overflow instructions
MO_Clz and MO_Ctz
Use PowerPC's CNTLZ instruction and implement count trailing
zeros using count leading zeros
MO_QuotRem2
Implement an algorithm given by Henry Warren in "Hacker's Delight"
using PowerPC divide instruction. TODO: Use long division instructions
when available (POWER7 and later).
Test Plan: validate on AIX and 32-bit Linux
Reviewers: simonmar, erikd, hvr, austin, bgamari
Reviewed By: erikd, hvr, bgamari
Subscribers: trofi, kgardas, thomie
Differential Revision: https://phabricator.haskell.org/D2973
Diffstat (limited to 'compiler/codeGen')
-rw-r--r-- | compiler/codeGen/StgCmmPrim.hs | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/compiler/codeGen/StgCmmPrim.hs b/compiler/codeGen/StgCmmPrim.hs index 0edde0659f..235109ffe9 100644 --- a/compiler/codeGen/StgCmmPrim.hs +++ b/compiler/codeGen/StgCmmPrim.hs @@ -815,33 +815,41 @@ type GenericOp = [CmmFormal] -> [CmmActual] -> FCode () callishPrimOpSupported :: DynFlags -> PrimOp -> Either CallishMachOp GenericOp callishPrimOpSupported dflags op = case op of - IntQuotRemOp | ncg && x86ish -> Left (MO_S_QuotRem (wordWidth dflags)) + IntQuotRemOp | ncg && (x86ish + || ppc) -> Left (MO_S_QuotRem (wordWidth dflags)) | otherwise -> Right (genericIntQuotRemOp dflags) - WordQuotRemOp | ncg && x86ish -> Left (MO_U_QuotRem (wordWidth dflags)) + WordQuotRemOp | ncg && (x86ish + || ppc) -> Left (MO_U_QuotRem (wordWidth dflags)) | otherwise -> Right (genericWordQuotRemOp dflags) - WordQuotRem2Op | (ncg && x86ish) + WordQuotRem2Op | (ncg && (x86ish + || ppc)) || llvm -> Left (MO_U_QuotRem2 (wordWidth dflags)) | otherwise -> Right (genericWordQuotRem2Op dflags) - WordAdd2Op | (ncg && x86ish) + WordAdd2Op | (ncg && (x86ish + || ppc)) || llvm -> Left (MO_Add2 (wordWidth dflags)) | otherwise -> Right genericWordAdd2Op - WordSubCOp | (ncg && x86ish) + WordSubCOp | (ncg && (x86ish + || ppc)) || llvm -> Left (MO_SubWordC (wordWidth dflags)) | otherwise -> Right genericWordSubCOp - IntAddCOp | (ncg && x86ish) + IntAddCOp | (ncg && (x86ish + || ppc)) || llvm -> Left (MO_AddIntC (wordWidth dflags)) | otherwise -> Right genericIntAddCOp - IntSubCOp | (ncg && x86ish) + IntSubCOp | (ncg && (x86ish + || ppc)) || llvm -> Left (MO_SubIntC (wordWidth dflags)) | otherwise -> Right genericIntSubCOp - WordMul2Op | ncg && x86ish + WordMul2Op | ncg && (x86ish + || ppc) || llvm -> Left (MO_U_Mul2 (wordWidth dflags)) | otherwise -> Right genericWordMul2Op FloatFabsOp | (ncg && x86ish) @@ -863,6 +871,10 @@ callishPrimOpSupported dflags op ArchX86 -> True ArchX86_64 -> True _ -> False + ppc = case platformArch (targetPlatform dflags) of + ArchPPC -> True + ArchPPC_64 _ -> True + _ -> False genericIntQuotRemOp :: DynFlags -> GenericOp genericIntQuotRemOp dflags [res_q, res_r] [arg_x, arg_y] |