summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2021-11-07 16:20:30 -0500
committerBen Gamari <ben@well-typed.com>2022-03-07 23:27:02 +0000
commit0d2414d7f50696c270bbefd9fea7dd059b2223db (patch)
tree4e4c15f5e4e6a5cdae420a5a0c4a5c3e73a1c8c9
parent1a0f8042165fde72dbbb474da10eeb72083126d2 (diff)
downloadhaskell-0d2414d7f50696c270bbefd9fea7dd059b2223db.tar.gz
cmm/opt: Ensure that div/mul folding produces valid Cmm
Cmm's shift operations expect the shift amount to be of full word width. However, previously the power-of-two div/mul folding logic would use the same width as the dividend, resulting in #20636.
-rw-r--r--compiler/cmm/CmmOpt.hs8
1 files changed, 5 insertions, 3 deletions
diff --git a/compiler/cmm/CmmOpt.hs b/compiler/cmm/CmmOpt.hs
index d6fdd5a23f..403fbd946a 100644
--- a/compiler/cmm/CmmOpt.hs
+++ b/compiler/cmm/CmmOpt.hs
@@ -345,10 +345,10 @@ cmmMachOpFoldM dflags mop [x, (CmmLit (CmmInt n _))]
= case mop of
MO_Mul rep
| Just p <- exactLog2 n ->
- Just (cmmMachOpFold dflags (MO_Shl rep) [x, CmmLit (CmmInt p rep)])
+ Just (cmmMachOpFold dflags (MO_Shl rep) [x, CmmLit (CmmInt p wordW)])
MO_U_Quot rep
| Just p <- exactLog2 n ->
- Just (cmmMachOpFold dflags (MO_U_Shr rep) [x, CmmLit (CmmInt p rep)])
+ Just (cmmMachOpFold dflags (MO_U_Shr rep) [x, CmmLit (CmmInt p wordW)])
MO_U_Rem rep
| Just _ <- exactLog2 n ->
Just (cmmMachOpFold dflags (MO_And rep) [x, CmmLit (CmmInt (n - 1) rep)])
@@ -356,7 +356,7 @@ cmmMachOpFoldM dflags mop [x, (CmmLit (CmmInt n _))]
| Just p <- exactLog2 n,
CmmReg _ <- x -> -- We duplicate x in signedQuotRemHelper, hence require
-- it is a reg. FIXME: remove this restriction.
- Just (cmmMachOpFold dflags (MO_S_Shr rep)
+ Just (cmmMachOpFold dflags (MO_S_Shr wordW)
[signedQuotRemHelper rep p, CmmLit (CmmInt p rep)])
MO_S_Rem rep
| Just p <- exactLog2 n,
@@ -370,6 +370,8 @@ cmmMachOpFoldM dflags mop [x, (CmmLit (CmmInt n _))]
[signedQuotRemHelper rep p, CmmLit (CmmInt (- n) rep)]])
_ -> Nothing
where
+ wordW = wordWidth dflags
+
-- In contrast with unsigned integers, for signed ones
-- shift right is not the same as quot, because it rounds
-- to minus infinity, whereas quot rounds toward zero.