diff options
author | Dominic Steinitz <dominic@steinitz.org> | 2017-03-07 09:26:16 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-03-07 13:32:33 -0500 |
commit | 12ccf767af3373e319b75d5d61fe79df4a389e45 (patch) | |
tree | ec4bf27785be88d67617ddddd5968e4c128fb6a1 /compiler/codeGen/StgCmmPrim.hs | |
parent | 48759c0ef0e7ce718b52557599ebbb884c19a2ad (diff) | |
download | haskell-12ccf767af3373e319b75d5d61fe79df4a389e45.tar.gz |
Generate better fp abs for X86 and llvm with default cmm otherwise
Currently we have this in libraries/base/GHC/Float.hs:
```
abs x | x == 0 = 0 -- handles (-0.0)
| x > 0 = x
| otherwise = negateFloat x
```
But 3-4 years ago it was noted that this was inefficient:
https://mail.haskell.org/pipermail/libraries/2013-April/019690.html
We can generate better code for X86 and llvm and for others generate
some custom cmm code which is similar to what the compiler generates
now.
Reviewers: austin, simonmar, hvr, bgamari
Reviewed By: bgamari
Subscribers: dfeuer, thomie
Differential Revision: https://phabricator.haskell.org/D3265
Diffstat (limited to 'compiler/codeGen/StgCmmPrim.hs')
-rw-r--r-- | compiler/codeGen/StgCmmPrim.hs | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/compiler/codeGen/StgCmmPrim.hs b/compiler/codeGen/StgCmmPrim.hs index 14eb4258de..0edde0659f 100644 --- a/compiler/codeGen/StgCmmPrim.hs +++ b/compiler/codeGen/StgCmmPrim.hs @@ -844,6 +844,12 @@ callishPrimOpSupported dflags op WordMul2Op | ncg && x86ish || llvm -> Left (MO_U_Mul2 (wordWidth dflags)) | otherwise -> Right genericWordMul2Op + FloatFabsOp | (ncg && x86ish) + || llvm -> Left MO_F32_Fabs + | otherwise -> Right $ genericFabsOp W32 + DoubleFabsOp | (ncg && x86ish) + || llvm -> Left MO_F64_Fabs + | otherwise -> Right $ genericFabsOp W64 _ -> pprPanic "emitPrimOp: can't translate PrimOp " (ppr op) where @@ -1064,6 +1070,34 @@ genericWordMul2Op [res_h, res_l] [arg_x, arg_y] topHalf (CmmReg r)])] genericWordMul2Op _ _ = panic "genericWordMul2Op" +-- This replicates what we had in libraries/base/GHC/Float.hs: +-- +-- abs x | x == 0 = 0 -- handles (-0.0) +-- | x > 0 = x +-- | otherwise = negateFloat x +genericFabsOp :: Width -> GenericOp +genericFabsOp w [res_r] [aa] + = do dflags <- getDynFlags + let zero = CmmLit (CmmFloat 0 w) + + eq x y = CmmMachOp (MO_F_Eq w) [x, y] + gt x y = CmmMachOp (MO_F_Gt w) [x, y] + + neg x = CmmMachOp (MO_F_Neg w) [x] + + g1 = catAGraphs [mkAssign (CmmLocal res_r) zero] + g2 = catAGraphs [mkAssign (CmmLocal res_r) aa] + + res_t <- CmmLocal <$> newTemp (cmmExprType dflags aa) + let g3 = catAGraphs [mkAssign res_t aa, + mkAssign (CmmLocal res_r) (neg (CmmReg res_t))] + + g4 <- mkCmmIfThenElse (gt aa zero) g2 g3 + + emit =<< mkCmmIfThenElse (eq aa zero) g1 g4 + +genericFabsOp _ _ _ = panic "genericFabsOp" + -- These PrimOps are NOPs in Cmm nopOp :: PrimOp -> Bool |