diff options
author | John Ericson <git@JohnEricson.me> | 2020-01-20 17:25:06 -0500 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-07-07 13:56:00 -0400 |
commit | 37743f91a3f5018a8894ca6d35e8b423e4e08b50 (patch) | |
tree | 044ea1644eccc152bc74297484f5e6c5d5066ef7 /compiler/GHC/CmmToLlvm | |
parent | e61d539527a7398017f759c67621ba18a15878f7 (diff) | |
download | haskell-37743f91a3f5018a8894ca6d35e8b423e4e08b50.tar.gz |
Support `timesInt2#` in LLVM backend
Diffstat (limited to 'compiler/GHC/CmmToLlvm')
-rw-r--r-- | compiler/GHC/CmmToLlvm/CodeGen.hs | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/compiler/GHC/CmmToLlvm/CodeGen.hs b/compiler/GHC/CmmToLlvm/CodeGen.hs index 6e424b7e48..555e2de9e7 100644 --- a/compiler/GHC/CmmToLlvm/CodeGen.hs +++ b/compiler/GHC/CmmToLlvm/CodeGen.hs @@ -343,7 +343,7 @@ genCall (PrimTarget (MO_U_Mul2 w)) [dstH, dstL] [lhs, rhs] = runStmtsDecls $ do retV <- doExprW width2x $ LlvmOp LM_MO_Mul lhsExt rhsExt -- Extract the lower bits of the result into retL. retL <- doExprW width $ Cast LM_Trunc retV width - -- Now we right-shift the higher bits by width. + -- Now we unsigned right-shift the higher bits by width. let widthLlvmLit = LMLitVar $ LMIntLit (fromIntegral bitWidth) width retShifted <- doExprW width2x $ LlvmOp LM_MO_LShr retV widthLlvmLit -- And extract them into retH. @@ -353,6 +353,31 @@ genCall (PrimTarget (MO_U_Mul2 w)) [dstH, dstL] [lhs, rhs] = runStmtsDecls $ do statement $ Store retL dstRegL statement $ Store retH dstRegH +genCall (PrimTarget (MO_S_Mul2 w)) [dstH, dstL] [lhs, rhs] = runStmtsDecls $ do + let width = widthToLlvmInt w + bitWidth = widthInBits w + width2x = LMInt (bitWidth * 2) + -- First sign-extend the operands ('mul' instruction requires the operands + -- and the result to be of the same type). Note that we don't use 'castVars' + -- because it tries to do LM_Sext. + lhsVar <- exprToVarW lhs + rhsVar <- exprToVarW rhs + lhsExt <- doExprW width2x $ Cast LM_Sext lhsVar width2x + rhsExt <- doExprW width2x $ Cast LM_Sext rhsVar width2x + -- Do the actual multiplication (note that the result is also 2x width). + retV <- doExprW width2x $ LlvmOp LM_MO_Mul lhsExt rhsExt + -- Extract the lower bits of the result into retL. + retL <- doExprW width $ Cast LM_Trunc retV width + -- Now we signed right-shift the higher bits by width. + let widthLlvmLit = LMLitVar $ LMIntLit (fromIntegral bitWidth) width + retShifted <- doExprW width2x $ LlvmOp LM_MO_AShr retV widthLlvmLit + -- And extract them into retH. + retH <- doExprW width $ Cast LM_Trunc retShifted width + dstRegL <- getCmmRegW (CmmLocal dstL) + dstRegH <- getCmmRegW (CmmLocal dstH) + statement $ Store retL dstRegL + statement $ Store retH dstRegH + -- MO_U_QuotRem2 is another case we handle by widening the registers to double -- the width and use normal LLVM instructions (similarly to the MO_U_Mul2). The -- main difference here is that we need to combine two words into one register |