Don't import FastString in HsVersions.h
[ghc-hetmet.git] / compiler / cmm / CmmOpt.hs
index 320f0a5..6adafb5 100644 (file)
@@ -30,13 +30,12 @@ import StaticFlags
 
 import UniqFM
 import Unique
-
+import FastTypes
 import Outputable
 
 import Data.Bits
 import Data.Word
 import Data.Int
-import GHC.Exts
 
 -- -----------------------------------------------------------------------------
 -- The mini-inliner
@@ -102,6 +101,11 @@ cmmMiniInline blocks = map do_inline blocks
 cmmMiniInlineStmts :: UniqFM Int -> [CmmStmt] -> [CmmStmt]
 cmmMiniInlineStmts uses [] = []
 cmmMiniInlineStmts uses (stmt@(CmmAssign (CmmLocal (LocalReg u _ _)) expr) : stmts)
+        -- not used at all: just discard this assignment
+  | Nothing <- lookupUFM uses u
+  = cmmMiniInlineStmts uses stmts
+
+        -- used once: try to inline at the use site
   | Just 1 <- lookupUFM uses u,
     Just stmts' <- lookForInline u expr stmts
   = 
@@ -151,7 +155,7 @@ inlineStmt u a (CmmCall target regs es srt ret)
    = CmmCall (infn target) regs es' srt ret
    where infn (CmmCallee fn cconv) = CmmCallee fn cconv
         infn (CmmPrim p) = CmmPrim p
-        es' = [ (inlineExpr u a e, hint) | (e,hint) <- es ]
+        es' = [ (CmmHinted (inlineExpr u a e) hint) | (CmmHinted e hint) <- es ]
 inlineStmt u a (CmmCondBranch e d) = CmmCondBranch (inlineExpr u a e) d
 inlineStmt u a (CmmSwitch e d) = CmmSwitch (inlineExpr u a e) d
 inlineStmt u a (CmmJump e d) = CmmJump (inlineExpr u a e) d
@@ -326,34 +330,53 @@ cmmMachOpFold (MO_Sub _) [CmmLit (CmmLabel lbl), CmmLit (CmmInt i rep)]
   = CmmLit (CmmLabelOff lbl (fromIntegral (negate (narrowU rep i))))
 
 
--- Comparison of literal with narrowed/widened operand: perform
--- the comparison at a different width, as long as the literal is
--- within range.
+-- Comparison of literal with widened operand: perform the comparison
+-- at the smaller width, as long as the literal is within range.
+
+-- We can't do the reverse trick, when the operand is narrowed:
+-- narrowing throws away bits from the operand, there's no way to do
+-- the same comparison at the larger size.
 
 #if i386_TARGET_ARCH || x86_64_TARGET_ARCH
 -- powerPC NCG has a TODO for I8/I16 comparisons, so don't try
 
 cmmMachOpFold cmp [CmmMachOp conv [x], CmmLit (CmmInt i _)]
-  | Just (rep, narrow) <- maybe_conversion conv,
-    Just narrow_cmp <- maybe_comparison cmp rep,
-    let narrow_i = narrow rep i,
-    narrow_i == i
-  = cmmMachOpFold narrow_cmp [x, CmmLit (CmmInt narrow_i rep)]
+  |     -- if the operand is widened:
+    Just (rep, signed, narrow_fn) <- maybe_conversion conv,
+        -- and this is a comparison operation:
+    Just narrow_cmp <- maybe_comparison cmp rep signed,
+        -- and the literal fits in the smaller size:
+    i == narrow_fn rep i
+        -- then we can do the comparison at the smaller size
+  = cmmMachOpFold narrow_cmp [x, CmmLit (CmmInt i rep)]
  where
-    maybe_conversion (MO_U_Conv from _) = Just (from, narrowU)
-    maybe_conversion (MO_S_Conv from _) = Just (from, narrowS)
+    maybe_conversion (MO_U_Conv from to)
+        | to > from
+        = Just (from, False, narrowU)
+    maybe_conversion (MO_S_Conv from to)
+        | to > from, not (isFloatingRep from)
+        = Just (from, True, narrowS)
+        -- don't attempt to apply this optimisation when the source
+        -- is a float; see #1916
     maybe_conversion _ = Nothing
     
-    maybe_comparison (MO_U_Gt _) rep = Just (MO_U_Gt rep)
-    maybe_comparison (MO_U_Ge _) rep = Just (MO_U_Ge rep)
-    maybe_comparison (MO_U_Lt _) rep = Just (MO_U_Lt rep)
-    maybe_comparison (MO_U_Le _) rep = Just (MO_U_Le rep)
-    maybe_comparison (MO_S_Gt _) rep = Just (MO_S_Gt rep)
-    maybe_comparison (MO_S_Ge _) rep = Just (MO_S_Ge rep)
-    maybe_comparison (MO_S_Lt _) rep = Just (MO_S_Lt rep)
-    maybe_comparison (MO_S_Le _) rep = Just (MO_S_Le rep)
-    maybe_comparison (MO_Eq   _) rep = Just (MO_Eq   rep)
-    maybe_comparison _ _ = Nothing
+        -- careful (#2080): if the original comparison was signed, but
+        -- we were doing an unsigned widen, then we must do an
+        -- unsigned comparison at the smaller size.
+    maybe_comparison (MO_U_Gt _) rep _     = Just (MO_U_Gt rep)
+    maybe_comparison (MO_U_Ge _) rep _     = Just (MO_U_Ge rep)
+    maybe_comparison (MO_U_Lt _) rep _     = Just (MO_U_Lt rep)
+    maybe_comparison (MO_U_Le _) rep _     = Just (MO_U_Le rep)
+    maybe_comparison (MO_Eq   _) rep _     = Just (MO_Eq   rep)
+    maybe_comparison (MO_S_Gt _) rep True  = Just (MO_S_Gt rep)
+    maybe_comparison (MO_S_Ge _) rep True  = Just (MO_S_Ge rep)
+    maybe_comparison (MO_S_Lt _) rep True  = Just (MO_S_Lt rep)
+    maybe_comparison (MO_S_Le _) rep True  = Just (MO_S_Le rep)
+    maybe_comparison (MO_S_Gt _) rep False = Just (MO_U_Gt rep)
+    maybe_comparison (MO_S_Ge _) rep False = Just (MO_U_Ge rep)
+    maybe_comparison (MO_S_Lt _) rep False = Just (MO_U_Lt rep)
+    maybe_comparison (MO_S_Le _) rep False = Just (MO_U_Le rep)
+    maybe_comparison _ _ _ = Nothing
 
 #endif
 
@@ -455,23 +478,26 @@ cmmMachOpFold mop args = CmmMachOp mop args
 -- Used to be in MachInstrs --SDM.
 -- ToDo: remove use of unboxery --SDM.
 
-w2i x = word2Int# x
-i2w x = int2Word# x
+-- Unboxery removed in favor of FastInt; but is the function supposed to fail
+-- on inputs >= 2147483648, or was that just an implementation artifact?
+-- And is this speed-critical, or can we just use Integer operations
+-- (including Data.Bits)?
+--  --Isaac Dupree
 
 exactLog2 :: Integer -> Maybe Integer
-exactLog2 x
-  = if (x <= 0 || x >= 2147483648) then
+exactLog2 x_
+  = if (x_ <= 0 || x_ >= 2147483648) then
        Nothing
     else
-       case fromInteger x of { I# x# ->
-       if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
+       case iUnbox (fromInteger x_) of { x ->
+       if (x `bitAndFastInt` negateFastInt x) /=# x then
          Nothing
        else
-         Just (toInteger (I# (pow2 x#)))
+         Just (toInteger (iBox (pow2 x)))
        }
   where
-    pow2 x# | x# ==# 1# = 0#
-            | otherwise = 1# +# pow2 (w2i (i2w x# `shiftRL#` 1#))
+    pow2 x | x ==# _ILIT(1) = _ILIT(0)
+           | otherwise = _ILIT(1) +# pow2 (x `shiftR_FastInt` _ILIT(1))
 
 
 -- -----------------------------------------------------------------------------
@@ -548,5 +574,3 @@ isComparisonExpr _other         = False
 isPicReg (CmmReg (CmmGlobal PicBaseReg)) = True
 isPicReg _ = False
 
-_unused :: FS.FastString -- stops a warning
-_unused = undefined