blob: 1962cc266e728d310fa2cdec90be37d10b4734a5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
{-
- A rather contrived example demonstrating the virtues of not floating join
- points outward.
-}
module Main (main) where
-- Calculate n `div` d `div` d by looping.
{-# NOINLINE slowDivDiv #-}
slowDivDiv :: Int -> Int -> Int
slowDivDiv n d
= let {-# NOINLINE divPos #-}
divPos :: Int -> Int
divPos n0
= -- This function is a join point (all calls are tail calls), so it
-- never causes a closure allocation, so it doesn't help to float it
-- out. Thus -fno-join-points causes a ~25% jump in allocations.
let go n' i
= case n' >= d of True -> go (n' - d) (i + 1)
False -> i
in go n0 0
in case n >= 0 of True -> divPos (divPos n)
False -> divPos (-(divPos (-n)))
-- It's important that divPos be called twice
-- because otherwise it'd be a one-shot lambda
-- and so the join point would be floated
-- back in again.
main = print $ sum [slowDivDiv n d | n <- [1..1000], d <- [1..1000]]
|