[project @ 2000-07-02 18:59:10 by panne]
authorpanne <unknown>
Sun, 2 Jul 2000 18:59:10 +0000 (18:59 +0000)
committerpanne <unknown>
Sun, 2 Jul 2000 18:59:10 +0000 (18:59 +0000)
Don't use addr2Integer for large integral literals anymore, use a
Horner schema with numbers in the Int range instead. This improves
constant folding, so e.g.  (0x87654321 :: Word32) is evaluated at
compile time now. In theory we can completely say Good-bye to
addr2Integer, but for the time being it's still there. Feel free to
nuke it...  >:-)

ghc/compiler/basicTypes/Literal.lhs
ghc/compiler/rename/RnExpr.lhs

index 016cc8e..907eba3 100644 (file)
@@ -12,7 +12,7 @@ module Literal
        , literalType, literalPrimRep
        , hashLiteral
 
-       , inIntRange, inWordRange
+       , inIntRange, inWordRange, tARGET_MAX_INT
 
        , word2IntLit, int2WordLit, char2IntLit, int2CharLit
        , float2IntLit, int2FloatLit, double2IntLit, int2DoubleLit
index 7bfa409..5102f54 100644 (file)
@@ -50,6 +50,9 @@ import Util           ( removeDups )
 import ListSetOps      ( unionLists )
 import Maybes          ( maybeToBool )
 import Outputable
+import Literal         ( inIntRange, tARGET_MAX_INT )
+import RdrName         ( mkSrcUnqual )
+import OccName         ( varName )
 \end{code}
 
 
@@ -288,6 +291,12 @@ rnExpr (HsIPVar v)
   = getIPName v                        `thenRn` \ name ->
     returnRn (HsIPVar name, emptyFVs)
 
+-- Special case for integral literals with a large magnitude:
+-- They are transformed into an expression involving only smaller
+-- integral literals. This improves constant folding.
+rnExpr (HsLit (HsInt i))
+  | not (inIntRange i) = rnExpr (horner tARGET_MAX_INT i)
+
 rnExpr (HsLit lit) 
   = litOccurrence lit          `thenRn` \ fvs ->
     returnRn (HsLit lit, fvs)
@@ -468,6 +477,17 @@ rnExpr e@(EAsPat _ _) = addErrRn (patSynErr e)     `thenRn_`
 
 rnExpr e@(ELazyPat _) = addErrRn (patSynErr e) `thenRn_`
                        returnRn (EWildPat, emptyFVs)
+
+-- Transform i into (x1 + (x2 + (x3 + (...) * b) * b) * b) with abs xi <= b
+horner :: Integer -> Integer -> RdrNameHsExpr
+horner b i | abs q <= 1 = if r == 0 || r == i then mkInt i else mkInt r `plus` mkInt (i-r)
+           | r == 0     =                 horner b q `times` mkInt b
+           | otherwise  = mkInt r `plus` (horner b q `times` mkInt b)
+   where (q,r)    = i `quotRem` b
+         mkInt i  = HsLit (HsInt i)
+         plus     = mkOp "+"
+         times    = mkOp "*"
+         mkOp op = \x y -> OpApp x (HsVar (mkSrcUnqual varName (_PK_ op))) (panic "fixity") y
 \end{code}
 
 %************************************************************************