| ... | 
... | 
@@ -395,26 +395,39 @@ cmmMachOpFoldM platform mop [x, (CmmLit (CmmInt 1 rep))] | 
| 
395
 | 
395
 | 
     one  = CmmLit (CmmInt 1 (wordWidth platform))
  | 
| 
396
 | 
396
 | 
 
  | 
| 
397
 | 
397
 | 
 -- Now look for multiplication/division by powers of 2 (integers).
  | 
| 
398
 | 
 
 | 
-
  | 
| 
399
 | 
 
 | 
-cmmMachOpFoldM platform mop [x, (CmmLit (CmmInt n _))]
  | 
| 
 
 | 
398
 | 
+--
  | 
| 
 
 | 
399
 | 
+-- Naively this is as simple a matter as left/right bit shifts,
  | 
| 
 
 | 
400
 | 
+-- but the Cmm representation if integral values quickly complicated the matter.
  | 
| 
 
 | 
401
 | 
+--
  | 
| 
 
 | 
402
 | 
+-- We must carefully narrow the value to be within the range of values for the
  | 
| 
 
 | 
403
 | 
+-- type's logical bit-width. However, Cmm only represents values as *signed*
  | 
| 
 
 | 
404
 | 
+-- integers internally yet the logical type may be unsigned. If we are dealing
  | 
| 
 
 | 
405
 | 
+-- with a negative integer type at width @_w@, the only negative number that
  | 
| 
 
 | 
406
 | 
+-- wraps around to be a positive power of 2 after calling narrowU is -2^(_w - 1)
  | 
| 
 
 | 
407
 | 
+-- which wraps round to 2^(_w - 1), and multiplying by -2^(_w - 1) is indeed
  | 
| 
 
 | 
408
 | 
+-- the same as a left shift by (w - 1), so this is OK.
  | 
| 
 
 | 
409
 | 
+--
  | 
| 
 
 | 
410
 | 
+-- ToDo: See #25664 (comment 605821) describing a change to the Cmm literal representation.
  | 
| 
 
 | 
411
 | 
+-- When/If this is completed, this code must be refactored to account for the explicit width sizes.
  | 
| 
 
 | 
412
 | 
+cmmMachOpFoldM platform mop [x, (CmmLit (CmmInt n _w))]
  | 
| 
400
 | 
413
 | 
   = case mop of
  | 
| 
401
 | 
414
 | 
         MO_Mul rep
  | 
| 
402
 | 
 
 | 
-           | Just p <- exactLog2 n ->
  | 
| 
 
 | 
415
 | 
+           | Just p <- exactLog2 (narrowU rep n) ->
  | 
| 
403
 | 
416
 | 
                  Just $! (cmmMachOpFold platform (MO_Shl rep) [x, CmmLit (CmmInt p $ wordWidth platform)])
  | 
| 
404
 | 
417
 | 
         MO_U_Quot rep
  | 
| 
405
 | 
 
 | 
-           | Just p <- exactLog2 n ->
  | 
| 
 
 | 
418
 | 
+           | Just p <- exactLog2 (narrowU rep n) ->
  | 
| 
406
 | 
419
 | 
                  Just $! (cmmMachOpFold platform (MO_U_Shr rep) [x, CmmLit (CmmInt p $ wordWidth platform)])
  | 
| 
407
 | 
420
 | 
         MO_U_Rem rep
  | 
| 
408
 | 
 
 | 
-           | Just _ <- exactLog2 n ->
  | 
| 
 
 | 
421
 | 
+           | Just _ <- exactLog2 (narrowU rep n)  ->
  | 
| 
409
 | 
422
 | 
                  Just $! (cmmMachOpFold platform (MO_And rep) [x, CmmLit (CmmInt (n - 1) rep)])
  | 
| 
410
 | 
423
 | 
         MO_S_Quot rep
  | 
| 
411
 | 
 
 | 
-           | Just p <- exactLog2 n,
  | 
| 
 
 | 
424
 | 
+           | Just p <- exactLog2 (narrowS rep n),
  | 
| 
412
 | 
425
 | 
              CmmReg _ <- x ->   -- We duplicate x in signedQuotRemHelper, hence require
  | 
| 
413
 | 
426
 | 
                                 -- it is a reg.  FIXME: remove this restriction.
  | 
| 
414
 | 
427
 | 
                 Just $! (cmmMachOpFold platform (MO_S_Shr rep)
  | 
| 
415
 | 
428
 | 
                   [signedQuotRemHelper rep p, CmmLit (CmmInt p $ wordWidth platform)])
  | 
| 
416
 | 
429
 | 
         MO_S_Rem rep
  | 
| 
417
 | 
 
 | 
-           | Just p <- exactLog2 n,
  | 
| 
 
 | 
430
 | 
+           | Just p <- exactLog2 (narrowS rep n),
  | 
| 
418
 | 
431
 | 
              CmmReg _ <- x ->   -- We duplicate x in signedQuotRemHelper, hence require
  | 
| 
419
 | 
432
 | 
                                 -- it is a reg.  FIXME: remove this restriction.
  | 
| 
420
 | 
433
 | 
                 -- We replace (x `rem` 2^p) by (x - (x `quot` 2^p) * 2^p).
  |