diff --git a/libraries/base/Data/OldList.hs b/libraries/base/Data/OldList.hs
index 7e79c34..e30bef0 100644
--- a/libraries/base/Data/OldList.hs
+++ b/libraries/base/Data/OldList.hs
@@ -520,11 +520,9 @@ pairWithNil x = (x, [])
 
 mapAccumLF :: (acc -> x -> (acc, y)) -> x -> (acc -> (acc, [y])) -> acc -> (acc, [y])
 {-# INLINE [0] mapAccumLF #-}
-mapAccumLF f = \x r -> oneShot (\s ->
-                         let (s', y)   = f s x
+mapAccumLF f = \x r s -> let (s', y)   = f s x
                              (s'', ys) = r s'
-                         in (s'', y:ys))
-  -- See Note [Left folds via right fold]
+                         in (s'', y:ys)
 
 
 -- | The 'mapAccumR' function behaves like a combination of 'map' and
diff --git a/libraries/base/GHC/List.hs b/libraries/base/GHC/List.hs
index ca3fb75..b752166 100644
--- a/libraries/base/GHC/List.hs
+++ b/libraries/base/GHC/List.hs
@@ -22,7 +22,7 @@ module GHC.List (
 
    map, (++), filter, concat,
    head, last, tail, init, uncons, null, length, (!!),
-   foldl, foldl', foldl1, foldl1', scanl, scanl1, scanl', foldr, foldr1,
+   foldl, foldl', foldl1, foldl1', scanl, scanl', scanl1, foldr, foldr1,
    scanr, scanr1, iterate, repeat, replicate, cycle,
    take, drop, sum, product, maximum, minimum, splitAt, takeWhile, dropWhile,
    span, break, reverse, and, or,
@@ -84,15 +84,11 @@ last [x]                =  x
 last (_:xs)             =  last xs
 last []                 =  errorEmptyList "last"
 #else
--- Use foldl to make last a good consumer.
--- This will compile to good code for the actual GHC.List.last.
--- (At least as long it is eta-expaned, otherwise it does not, #10260.)
-last xs = foldl (\_ x -> x) lastError xs
-{-# INLINE last #-}
--- The inline pragma is required to make GHC remember the implementation via
--- foldl.
-lastError :: a
-lastError = errorEmptyList "last"
+-- eliminate repeated cases
+last []                 =  errorEmptyList "last"
+last (x:xs)             =  last' x xs
+  where last' y []     = y
+        last' _ (y:ys) = last' y ys
 #endif
 
 -- | Return all the elements of a list except the last one.
@@ -186,38 +182,19 @@ filterFB c p x r | p x       = x `c` r
 -- can be inlined, and then (often) strictness-analysed,
 -- and hence the classic space leak on foldl (+) 0 xs
 
-foldl :: forall a b. (b -> a -> b) -> b -> [a] -> b
-{-# INLINE foldl #-}
-foldl k z0 xs =
-  foldr (\(v::a) (fn::b->b) -> oneShot (\(z::b) -> fn (k z v))) (id :: b -> b) xs z0
-  -- See Note [Left folds via right fold]
-
-{-
-Note [Left folds via right fold]
-
-Implementing foldl et. al. via foldr is only a good idea if the compiler can
-optimize the resulting code (eta-expand the recursive "go"). See #7994.
-We hope that one of the two measure kick in:
-
-   * Call Arity (-fcall-arity, enabled by default) eta-expands it if it can see
-     all calls and determine that the arity is large.
-   * The oneShot annotation gives a hint to the regular arity analysis that
-     it may assume that the lambda is called at most once.
-     See [One-shot lambdas] in CoreArity and especially [Eta expanding thunks]
-     in CoreArity.
-
-The oneShot annotations used in this module are correct, as we only use them in
-argumets to foldr, where we know how the arguments are called.
--}
+foldl        :: (b -> a -> b) -> b -> [a] -> b
+foldl f z0 xs0 = lgo z0 xs0
+             where
+                lgo z []     =  z
+                lgo z (x:xs) = lgo (f z x) xs
 
 -- ----------------------------------------------------------------------------
 
 -- | A strict version of 'foldl'.
-foldl'           :: forall a b . (b -> a -> b) -> b -> [a] -> b
-{-# INLINE foldl' #-}
-foldl' k z0 xs =
-  foldr (\(v::a) (fn::b->b) -> oneShot (\(z::b) -> z `seq` fn (k z v))) (id :: b -> b) xs z0
-  -- See Note [Left folds via right fold]
+foldl'           :: (b -> a -> b) -> b -> [a] -> b
+foldl' f z0 xs0 = lgo z0 xs0
+    where lgo z []     = z
+          lgo z (x:xs) = let z' = f z x in z' `seq` lgo z' xs
 
 -- | 'foldl1' is a variant of 'foldl' that has no starting value argument,
 -- and thus must be applied to non-empty lists.
@@ -233,15 +210,33 @@ foldl1' _ []             =  errorEmptyList "foldl1'"
 -- -----------------------------------------------------------------------------
 -- List sum and product
 
+{-# SPECIALISE sum     :: [Int] -> Int #-}
+{-# SPECIALISE sum     :: [Integer] -> Integer #-}
+{-# INLINABLE sum #-}
+{-# SPECIALISE product :: [Int] -> Int #-}
+{-# SPECIALISE product :: [Integer] -> Integer #-}
+{-# INLINABLE product #-}
+-- We make 'sum' and 'product' inlinable so that we get specialisations
+-- at other types.  See, for example, Trac #7507.
+
 -- | The 'sum' function computes the sum of a finite list of numbers.
 sum                     :: (Num a) => [a] -> a
-{-# INLINE sum #-}
-sum                     =  foldl (+) 0
-
 -- | The 'product' function computes the product of a finite list of numbers.
 product                 :: (Num a) => [a] -> a
-{-# INLINE product #-}
-product                 =  foldl (*) 1
+
+#ifdef USE_REPORT_PRELUDE
+ sum                     =  foldl (+) 0
+ product                 =  foldl (*) 1
+#else
+sum     l       = sum' l 0
+  where
+    sum' []     a = a
+    sum' (x:xs) a = sum' xs (a+x)
+product l       = prod l 1
+  where
+    prod []     a = a
+    prod (x:xs) a = prod xs (a*x)
+#endif
 
 -- | 'scanl' is similar to 'foldl', but returns a list of successive
 -- reduced values from the left:
@@ -252,34 +247,9 @@ product                 =  foldl (*) 1
 --
 -- > last (scanl f z xs) == foldl f z xs.
 
--- This peculiar arrangement is necessary to prevent scanl being rewritten in
--- its own right-hand side.
-{-# NOINLINE [1] scanl #-}
-scanl                   :: (b -> a -> b) -> b -> [a] -> [b]
-scanl                   = scanlGo
-  where
-    scanlGo           :: (b -> a -> b) -> b -> [a] -> [b]
-    scanlGo f q ls    = q : (case ls of
-                               []   -> []
-                               x:xs -> scanlGo f (f q x) xs)
-
--- Note [scanl rewrite rules]
-{-# RULES
-"scanl"  [~1] forall f a bs . scanl f a bs =
-  build (\c n -> a `c` foldr (scanlFB f c) (constScanl n) bs a)
-"scanlList" [1] forall f (a::a) bs .
-    foldr (scanlFB f (:)) (constScanl []) bs a = tail (scanl f a bs)
- #-}
-
-{-# INLINE [0] scanlFB #-}
-scanlFB :: (b -> a -> b) -> (b -> c -> c) -> a -> (b -> c) -> b -> c
-scanlFB f c = \b g -> oneShot (\x -> let b' = f x b in b' `c` g b')
-  -- See Note [Left folds via right fold]
-
-{-# INLINE [0] constScanl #-}
-constScanl :: a -> b -> a
-constScanl = const
-
+scanl f q ls            =  q : (case ls of
+                                []   -> []
+                                x:xs -> scanl f (f q x) xs)
 
 -- | 'scanl1' is a variant of 'scanl' that has no starting value argument:
 --
@@ -301,53 +271,6 @@ scanl' = scanlGo'
                             []   -> []
                             x:xs -> scanlGo' f (f q x) xs)
 
--- Note [scanl rewrite rules]
-{-# RULES
-"scanl'"  [~1] forall f a bs . scanl' f a bs =
-  build (\c n -> a `c` foldr (scanlFB' f c) (flipSeqScanl' n) bs a)
-"scanlList'" [1] forall f a bs .
-    foldr (scanlFB' f (:)) (flipSeqScanl' []) bs a = tail (scanl' f a bs)
- #-}
-
-{-# INLINE [0] scanlFB' #-}
-scanlFB' :: (b -> a -> b) -> (b -> c -> c) -> a -> (b -> c) -> b -> c
-scanlFB' f c = \b g -> oneShot (\x -> let !b' = f x b in b' `c` g b')
-  -- See Note [Left folds via right fold]
-
-{-# INLINE [0] flipSeqScanl' #-}
-flipSeqScanl' :: a -> b -> a
-flipSeqScanl' a !_b = a
-
-{-
-Note [scanl rewrite rules]
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In most cases, when we rewrite a form to one that can fuse, we try to rewrite it
-back to the original form if it does not fuse. For scanl, we do something a
-little different. In particular, we rewrite
-
-scanl f a bs
-
-to
-
-build (\c n -> a `c` foldr (scanlFB f c) (constScanl n) bs a)
-
-When build is inlined, this becomes
-
-a : foldr (scanlFB f (:)) (constScanl []) bs a
-
-To rewrite this form back to scanl, we would need a rule that looked like
-
-forall f a bs. a : foldr (scanlFB f (:)) (constScanl []) bs a = scanl f a bs
-
-The problem with this rule is that it has (:) at its head. This would have the
-effect of changing the way the inliner looks at (:), not only here but
-everywhere.  In most cases, this makes no difference, but in some cases it
-causes it to come to a different decision about whether to inline something.
-Based on nofib benchmarks, this is bad for performance. Therefore, we instead
-match on everything past the :, which is just the tail of scanl.
--}
-
 -- foldr, foldr1, scanr, and scanr1 are the right-to-left duals of the
 -- above functions.
 
diff --git a/testsuite/tests/perf/should_run/T9339.hs b/testsuite/tests/perf/should_run/T9339.hs
deleted file mode 100644
index 96f5f72..0000000
--- a/testsuite/tests/perf/should_run/T9339.hs
+++ /dev/null
@@ -1,4 +0,0 @@
--- Tests that `last` successfully fuses.
-
-main :: IO ()
-main = print $ last $ filter odd $ [1::Int ..10000000]
diff --git a/testsuite/tests/perf/should_run/T9339.stdout b/testsuite/tests/perf/should_run/T9339.stdout
deleted file mode 100644
index e161ae3..0000000
--- a/testsuite/tests/perf/should_run/T9339.stdout
+++ /dev/null
@@ -1 +0,0 @@
-9999999
diff --git a/testsuite/tests/perf/should_run/all.T b/testsuite/tests/perf/should_run/all.T
index d34a277..04469b1 100644
--- a/testsuite/tests/perf/should_run/all.T
+++ b/testsuite/tests/perf/should_run/all.T
@@ -16,11 +16,10 @@ test('T3586',
 
 test('T4830',
      [stats_num_field('bytes allocated',
-          [(wordsize(64), 98784, 1),
+          [(wordsize(64), 98248, 1),
            #             127000 (amd64/Linux)
            # 2013-02-07:  99264 (amd64/Linux)
            # 2014-01-13:  98248 (amd64/Linux) due to #8647
-           # 2015-07-09:  98784 (amd64/Linux)
            (wordsize(32), 70646, 3)]),
            # 2013-02-10:  69744 (x86/Windows)
            # 2013-02-10:  71548 (x86/OSX)
@@ -97,10 +96,9 @@ test('T3738',
       stats_num_field('bytes allocated',
                       [(wordsize(32), 45648, 5),
                     # expected value: 50520 (x86/Linux)
-                       (wordsize(64), 50592, 5)]),
+                       (wordsize(64), 49400, 5)]),
                     # prev:           49400 (amd64/Linux)
                     # 2014-07-17:     50520 (amd64/Linux) general round of updates
-                    # 2014-09-10:     50592 (amd64/Linux) post-AMP-update
       only_ways(['normal'])
       ],
      compile_and_run,
@@ -172,13 +170,10 @@ test('T5205',
 
 test('T5549',
      [stats_num_field('bytes allocated',
-                      [(wordsize(32), 4096606332, 5),
+                      [(wordsize(32), 3362958676, 5),
                     # expected value: 3362958676 (Windows)
-                    # 2014-12-01:     4096606332 (Windows) integer-gmp2
-
-                       (wordsize(64), 8193140752, 5)]),
+                       (wordsize(64), 6725846120, 5)]),
                     # expected value: 6725846120 (amd64/Linux)
-                    #                 8193140752 (amd64/Linux) integer-gmp2
       only_ways(['normal'])
       ],
      compile_and_run,
@@ -280,13 +275,12 @@ test('T7507', omit_ways(['ghci']), compile_and_run, ['-O'])
 
 test('T7436',
      [stats_num_field('max_bytes_used',
-          [(wordsize(64), 60296, 1),
+          [(wordsize(64), 60360, 1),
            #             127000 (amd64/Linux)
            # 2013-02-07:  60360 (amd64/Linux)
-           # 2015-07-09:  60296 (amd64/Linux)
            (wordsize(32), 58434, 1)]),
-           # 2013-02-10: 58032 (x86/Windows)
-           # 2013-02-10: 58836 (x86/OSX)
+            # 2013-02-10: 58032 (x86/Windows)
+            # 2013-02-10: 58836 (x86/OSX)
       only_ways(['normal'])
       ],
      compile_and_run,
