diff options
author | Ben Gamari <ben@smart-cactus.org> | 2021-11-07 16:20:30 -0500 |
---|---|---|
committer | Ben Gamari <ben@well-typed.com> | 2022-03-07 23:27:02 +0000 |
commit | 0d2414d7f50696c270bbefd9fea7dd059b2223db (patch) | |
tree | 4e4c15f5e4e6a5cdae420a5a0c4a5c3e73a1c8c9 | |
parent | 1a0f8042165fde72dbbb474da10eeb72083126d2 (diff) | |
download | haskell-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.hs | 8 |
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. |