diff options
author | Joachim Breitner <mail@joachim-breitner.de> | 2015-03-30 10:20:14 +0200 |
---|---|---|
committer | Joachim Breitner <mail@joachim-breitner.de> | 2015-03-30 10:22:27 +0200 |
commit | de1160be047790afde4ec76de0a81ba3be0c73fa (patch) | |
tree | 269bbb98b8451d2cf1ccf1a86dfaae69f2acb50e /compiler/cmm/PprCmm.hs | |
parent | e24f638158f96f80e476000cd7ce8555987d84f2 (diff) | |
download | haskell-de1160be047790afde4ec76de0a81ba3be0c73fa.tar.gz |
Refactor the story around switches (#10137)
This re-implements the code generation for case expressions at the Stg →
Cmm level, both for data type cases as well as for integral literal
cases. (Cases on float are still treated as before).
The goal is to allow for fancier strategies in implementing them, for a
cleaner separation of the strategy from the gritty details of Cmm, and
to run this later than the Common Block Optimization, allowing for one
way to attack #10124. The new module CmmSwitch contains a number of
notes explaining this changes. For example, it creates larger
consecutive jump tables than the previous code, if possible.
nofib shows little significant overall improvement of runtime. The
rather large wobbling comes from changes in the code block order
(see #8082, not much we can do about it). But the decrease in code size
alone makes this worthwhile.
```
Program Size Allocs Runtime Elapsed TotalMem
Min -1.8% 0.0% -6.1% -6.1% -2.9%
Max -0.7% +0.0% +5.6% +5.7% +7.8%
Geometric Mean -1.4% -0.0% -0.3% -0.3% +0.0%
```
Compilation time increases slightly:
```
-1 s.d. ----- -2.0%
+1 s.d. ----- +2.5%
Average ----- +0.3%
```
The test case T783 regresses a lot, but it is the only one exhibiting
any regression. The cause is the changed order of branches in an
if-then-else tree, which makes the hoople data flow analysis traverse
the blocks in a suboptimal order. Reverting that gets rid of this
regression, but has a consistent, if only very small (+0.2%), negative
effect on runtime. So I conclude that this test is an extreme outlier
and no reason to change the code.
Differential Revision: https://phabricator.haskell.org/D720
Diffstat (limited to 'compiler/cmm/PprCmm.hs')
-rw-r--r-- | compiler/cmm/PprCmm.hs | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/compiler/cmm/PprCmm.hs b/compiler/cmm/PprCmm.hs index 9d9f3081dc..d5999f53fa 100644 --- a/compiler/cmm/PprCmm.hs +++ b/compiler/cmm/PprCmm.hs @@ -43,6 +43,7 @@ import BlockId () import CLabel import Cmm import CmmUtils +import CmmSwitch import DynFlags import FastString import Outputable @@ -228,25 +229,31 @@ pprNode node = pp_node <+> pp_debug , ppr f <> semi ] - CmmSwitch expr maybe_ids -> - hang (hcat [ ptext (sLit "switch [0 .. ") - , int (length maybe_ids - 1) - , ptext (sLit "] ") + CmmSwitch expr ids -> + hang (hsep [ ptext (sLit "switch") + , range , if isTrivialCmmExpr expr then ppr expr else parens (ppr expr) - , ptext (sLit " {") + , ptext (sLit "{") ]) - 4 (vcat ( map caseify pairs )) $$ rbrace - where pairs = groupBy snds (zip [0 .. ] maybe_ids ) - snds a b = (snd a) == (snd b) - caseify ixs@((_,Nothing):_) = ptext (sLit "/* impossible: ") - <> hcat (intersperse comma (map (int.fst) ixs)) <> ptext (sLit " */") - caseify as = let (is,ids) = unzip as - in hsep [ ptext (sLit "case") - , hcat (punctuate comma (map int is)) - , ptext (sLit ": goto") - , ppr (head [ id | Just id <- ids]) <> semi ] + 4 (vcat (map ppCase cases) $$ def) $$ rbrace + where + (cases, mbdef) = switchTargetsFallThrough ids + ppCase (is,l) = hsep + [ ptext (sLit "case") + , commafy $ map integer is + , ptext (sLit ": goto") + , ppr l <> semi + ] + def | Just l <- mbdef = hsep + [ ptext (sLit "default: goto") + , ppr l <> semi + ] + | otherwise = empty + + range = brackets $ hsep [integer lo, ptext (sLit ".."), integer hi] + where (lo,hi) = switchTargetsRange ids CmmCall tgt k regs out res updfr_off -> hcat [ ptext (sLit "call"), space |