#include "HsVersions.h"
import Cmm
-import CmmUtils ( hasNoGlobalRegs )
-import CLabel ( entryLblToInfoLbl )
+import CmmUtils
+import CLabel
import MachOp
-import SMRep ( tablesNextToCode )
+import SMRep
+import StaticFlags
import UniqFM
-import Unique ( Unique )
-import Panic ( panic )
+import Unique
import Outputable
-import Bits
-import Word
-import Int
-import GLAEXTS
-
+import Data.Bits
+import Data.Word
+import Data.Int
+import GHC.Exts
-- -----------------------------------------------------------------------------
-- The mini-inliner
-- put arg1 on the left of the rearranged expression, we'll get into a
-- loop: (x1+x2)+x3 => x1+(x2+x3) => (x2+x3)+x1 => x2+(x3+x1) ...
--
+-- Also don't do it if arg1 is PicBaseReg, so that we don't separate the
+-- PicBaseReg from the corresponding label (or label difference).
+--
cmmMachOpFold mop1 [CmmMachOp mop2 [arg1,arg2], arg3]
- | mop1 == mop2 && isAssociativeMachOp mop1 && not (isLit arg1)
+ | mop1 == mop2 && isAssociativeMachOp mop1
+ && not (isLit arg1) && not (isPicReg arg1)
= cmmMachOpFold mop1 [arg1, cmmMachOpFold mop2 [arg2,arg3]]
-- Make a RegOff if we can
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.
+
+#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)]
+ where
+ maybe_conversion (MO_U_Conv from _) = Just (from, narrowU)
+ maybe_conversion (MO_S_Conv from _) = Just (from, narrowS)
+ 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
+
+#endif
+
-- We can often do something with constants of 0 and 1 ...
cmmMachOpFold mop args@[x, y@(CmmLit (CmmInt 0 _))]
cmmMachOpFold mop args@[x, y@(CmmLit (CmmInt n _))]
= case mop of
MO_Mul rep
- -> case exactLog2 n of
- Nothing -> unchanged
- Just p -> CmmMachOp (MO_Shl rep) [x, CmmLit (CmmInt p rep)]
+ | Just p <- exactLog2 n ->
+ CmmMachOp (MO_Shl rep) [x, CmmLit (CmmInt p rep)]
MO_S_Quot rep
- -> case exactLog2 n of
- Nothing -> unchanged
- Just p -> CmmMachOp (MO_S_Shr rep) [x, CmmLit (CmmInt p rep)]
- other
+ | Just p <- exactLog2 n,
+ CmmReg _ <- x -> -- We duplicate x below, hence require
+ -- it is a reg. FIXME: remove this restriction.
+ -- shift right is not the same as quot, because it rounds
+ -- to minus infinity, whereasq uot rounds toward zero.
+ -- To fix this up, we add one less than the divisor to the
+ -- dividend if it is a negative number.
+ --
+ -- to avoid a test/jump, we use the following sequence:
+ -- x1 = x >> word_size-1 (all 1s if -ve, all 0s if +ve)
+ -- x2 = y & (divisor-1)
+ -- result = (x+x2) >>= log2(divisor)
+ -- this could be done a bit more simply using conditional moves,
+ -- but we're processor independent here.
+ --
+ -- we optimise the divide by 2 case slightly, generating
+ -- x1 = x >> word_size-1 (unsigned)
+ -- return = (x + x1) >>= log2(divisor)
+ let
+ bits = fromIntegral (machRepBitWidth rep) - 1
+ shr = if p == 1 then MO_U_Shr rep else MO_S_Shr rep
+ x1 = CmmMachOp shr [x, CmmLit (CmmInt bits rep)]
+ x2 = if p == 1 then x1 else
+ CmmMachOp (MO_And rep) [x1, CmmLit (CmmInt (n-1) rep)]
+ x3 = CmmMachOp (MO_Add rep) [x, x2]
+ in
+ CmmMachOp (MO_S_Shr rep) [x3, CmmLit (CmmInt p rep)]
+ other
-> unchanged
where
unchanged = CmmMachOp mop args
maybeInvertConditionalExpr (CmmMachOp op args)
| Just op' <- maybeInvertComparison op = Just (CmmMachOp op' args)
maybeInvertConditionalExpr _ = Nothing
+
+isPicReg (CmmReg (CmmGlobal PicBaseReg)) = True
+isPicReg _ = False