From 6b17fd584e9135b2c1eed1d3ff5b2c42322c2b73 Mon Sep 17 00:00:00 2001
From: Daniel Fischer <daniel.is.fischer@googlemail.com>
Date: Sat, 1 Oct 2011 21:15:22 +0200
Subject: [PATCH] Add rules for powers with small exponents (fixes #5237)

---
 GHC/Real.lhs |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/GHC/Real.lhs b/GHC/Real.lhs
index 8597c45..125713d 100644
--- a/GHC/Real.lhs
+++ b/GHC/Real.lhs
@@ -469,6 +469,44 @@ x ^^ n          =  if n >= 0 then x^n else recip (x^(negate n))
              \d1 d2 x y -> blah
    after the gentle round of simplification. -}
 
+{- Rules for powers with known small exponent
+    see #5237
+    For small exponents, (^) is inefficient compared to manually
+    expanding the multiplication tree.
+    Here, rules for the most common exponent types are given.
+    The range of exponents for which rules are given is quite
+    arbitrary and kept small to not unduly increase the number of rules.
+    0 and 1 are excluded based on the assumption that nobody would
+    write x^0 or x^1 in code and the cases where an exponent could
+    be statically resolved to 0 or 1 are rare.
+-}
+
+{-# RULES
+"^2/Int"        forall x. x ^ (2 :: Int) = let u = x in u*u
+"^3/Int"        forall x. x ^ (3 :: Int) = let u = x in (u*u)*u
+"^4/Int"        forall x. x ^ (4 :: Int) = let u = x; y = u*u in y*y
+"^2/Integer"    forall x. x ^ (2 :: Integer) = let u = x in u*u
+"^3/Integer"    forall x. x ^ (3 :: Integer) = let u = x in (u*u)*u
+"^4/Integer"    forall x. x ^ (4 :: Integer) = let u = x; y = u*u in y*y
+  #-}
+
+{- With the above, (x :: Type1) ^ (2 :: Type2) isn't rewritten if
+   there is a specialisation for (^) :: Type1 -> Type2 -> Type1,
+   hence special rules for those cases.
+-}
+
+{-# RULES
+"^2/Int2"       forall (x :: Int). x ^ (2 :: Int) = let u = x in u*u
+"^3/Int2"       forall (x :: Int). x ^ (3 :: Int) = let u = x in (u*u)*u
+"^4/Int2"       forall (x :: Int). x ^ (4 :: Int) = let u = x; y = u*u in y*y
+"^2/Integer2"   forall (x :: Integer). x ^ (2 :: Integer) = let u = x in u*u
+"^3/Integer2"   forall (x :: Integer). x ^ (3 :: Integer) = let u = x in (u*u)*u
+"^4/Integer2"   forall (x :: Integer). x ^ (4 :: Integer) = let u = x; y = u*u in y*y
+"^2/Integer3"   forall (x :: Integer). x ^ (2 :: Int) = let u = x in u*u
+"^3/Integer3"   forall (x :: Integer). x ^ (3 :: Int) = let u = x in (u*u)*u
+"^4/Integer3"   forall (x :: Integer). x ^ (4 :: Int) = let u = x; y = u*u in y*y
+  #-}
+
 -------------------------------------------------------
 -- Special power functions for Rational
 --
-- 
1.7.3.4

