From 2a0ffd1c424b2c076506841a55fa6f45d85329bb Mon Sep 17 00:00:00 2001
From: panne <unknown>
Date: Sun, 2 Jul 2000 18:59:10 +0000
Subject: [PATCH] [project @ 2000-07-02 18:59:10 by panne] 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 |  2 +-
 ghc/compiler/rename/RnExpr.lhs      | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/ghc/compiler/basicTypes/Literal.lhs b/ghc/compiler/basicTypes/Literal.lhs
index 016cc8e332ab..907eba3ce04e 100644
--- a/ghc/compiler/basicTypes/Literal.lhs
+++ b/ghc/compiler/basicTypes/Literal.lhs
@@ -12,7 +12,7 @@ module Literal
 	, literalType, literalPrimRep
 	, hashLiteral
 
-	, inIntRange, inWordRange
+	, inIntRange, inWordRange, tARGET_MAX_INT
 
 	, word2IntLit, int2WordLit, char2IntLit, int2CharLit
 	, float2IntLit, int2FloatLit, double2IntLit, int2DoubleLit
diff --git a/ghc/compiler/rename/RnExpr.lhs b/ghc/compiler/rename/RnExpr.lhs
index 7bfa40982100..5102f544a1fc 100644
--- a/ghc/compiler/rename/RnExpr.lhs
+++ b/ghc/compiler/rename/RnExpr.lhs
@@ -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}
 
 %************************************************************************
-- 
GitLab