Strange interaction between simplification and cost centers
The `ghc` manual [says](https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#inserting-cost-centres-by-hand)
> the optimiser is careful to not move them around or remove [cost centres]
but experiments suggest that this is not always the case. Some examples will follow.
Tested with 9.10 and 10.0.
## Variant A: manual cost centers on function declarations
```hs
{-# OPTIONS_GHC -fno-prof-auto #-}
module DemoCallStack (main) where
import Control.Exception.Backtrace
{-# SCC bottom #-}
bottom :: IO ()
bottom = do
bt <- collectBacktraces
putStrLn $ displayBacktraces bt
{-# SCC middle #-}
middle :: IO ()
middle = bottom
{-# SCC top #-}
top :: IO ()
top = middle
{-# SCC main #-}
main :: IO ()
main = do
setBacktraceMechanismState CostCentreBacktrace True
top
```
outputs
```
Cost-centre stack backtrace:
DemoCallStack.DemoCallStack.main (exe/DemoCallStack.hs:31:1-4)
DemoCallStack.DemoCallStack.bottom (exe/DemoCallStack.hs:14:1-6)
```
where `top` and `middle` have disappeared.
## Variant B: manual cost centers on function bodies
```hs
{-# OPTIONS_GHC -fno-prof-auto #-}
module DemoCallStack (main) where
import Control.Exception.Backtrace
bottom :: IO ()
bottom = {-# SCC "bottom" #-} do
bt <- collectBacktraces
putStrLn $ displayBacktraces bt
middle :: IO ()
middle = {-# SCC "middle" #-} bottom
top :: IO ()
top = {-# SCC "top" #-} middle
main :: IO ()
main = {-# SCC "main" #-} do
setBacktraceMechanismState CostCentreBacktrace True
top
```
has the same output as variant A:
```
Cost-centre stack backtrace:
DemoCallStack.main (exe/DemoCallStack.hs:(30,27)-(33,7))
DemoCallStack.bottom (exe/DemoCallStack.hs:(13,31)-(16,35))
```
## Variant C: automatic top-level cost centers
```hs
{-# OPTIONS_GHC -fprof-auto #-}
module DemoCallStack (main) where
import Control.Exception.Backtrace
bottom :: IO ()
bottom = do
bt <- collectBacktraces
putStrLn $ displayBacktraces bt
middle :: IO ()
middle = bottom
top :: IO ()
top = middle
main :: IO ()
main = do
setBacktraceMechanismState CostCentreBacktrace True
top
```
same output again:
```
Cost-centre stack backtrace:
DemoCallStack.main (exe/DemoCallStack.hs:(31,1)-(33,7))
DemoCallStack.bottom (exe/DemoCallStack.hs:(14,1)-(16,35))
```
## Variant D: manual cost centers on declarations _and_ automatic cost centers
Now it gets weird:
```hs
{-# OPTIONS_GHC -fprof-auto #-}
module DemoCallStack (main) where
import Control.Exception.Backtrace
{-# SCC bottom #-}
bottom :: IO ()
bottom = do
bt <- collectBacktraces
putStrLn $ displayBacktraces bt
{-# SCC middle #-}
middle :: IO ()
middle = bottom
{-# SCC top #-}
top :: IO ()
top = middle
{-# SCC main #-}
main :: IO ()
main = do
setBacktraceMechanismState CostCentreBacktrace True
top
```
outputs
```
Cost-centre stack backtrace:
DemoCallStack.main (exe/DemoCallStack.hs:(31,1)-(33,7))
DemoCallStack.DemoCallStack.main (exe/DemoCallStack.hs:31:1-4)
DemoCallStack.top (exe/DemoCallStack.hs:26:1-12)
DemoCallStack.middle (exe/DemoCallStack.hs:21:1-15)
DemoCallStack.bottom (exe/DemoCallStack.hs:(14,1)-(16,35))
DemoCallStack.DemoCallStack.bottom (exe/DemoCallStack.hs:14:1-6)
```
Note that
* `main` and `bottom` now appear _twice_ (justifiably)
* suddenly `top` and `middle` _do_ appear, once!
It's as if we need _two_ cost centers before we really prevent inlining?
## Variant E: manual cost centers on both function declaration and body
Confirming the "two cost centers" theory:
```hs
{-# OPTIONS_GHC -fno-prof-auto #-}
module DemoCallStack (main) where
import Control.Exception.Backtrace
{-# SCC bottom #-}
bottom :: IO ()
bottom = {-# SCC "bottom" #-} do
bt <- collectBacktraces
putStrLn $ displayBacktraces bt
{-# SCC middle #-}
middle :: IO ()
middle = {-# SCC "middle" #-} bottom
{-# SCC top #-}
top :: IO ()
top = {-# SCC "top" #-} middle
{-# SCC main #-}
main :: IO ()
main = {-# SCC "main" #-} do
setBacktraceMechanismState CostCentreBacktrace True
top
```
outputs
```
DemoCallStack.DemoCallStack.main (exe/DemoCallStack.hs:30:1-4)
DemoCallStack.main (exe/DemoCallStack.hs:(30,27)-(33,7))
DemoCallStack.DemoCallStack.top (exe/DemoCallStack.hs:25:1-3)
DemoCallStack.DemoCallStack.middle (exe/DemoCallStack.hs:20:1-6)
DemoCallStack.DemoCallStack.bottom (exe/DemoCallStack.hs:13:1-6)
DemoCallStack.bottom (exe/DemoCallStack.hs:(13,31)-(16,35))
```
This is almost the same as in variant D: again `main` and `bottom` appear twice, `top` and `middle` once. The only difference is in the same; presumably automatic cost center placement inserts cost centers with slightly different names, not that important.
issue