]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: lay out exit blocks last
authorJosh Bleecher Snyder <josharian@gmail.com>
Fri, 12 May 2017 13:10:25 +0000 (06:10 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 16 May 2017 13:46:10 +0000 (13:46 +0000)
In Go 1.8.x, panics are generally scheduled at the very end of functions.
That property was lost in Go 1.9; this CL restores it.

This helps with the Fannkuch benchmark:

name          old time/op  new time/op  delta
Fannkuch11-8   2.74s ± 2%   2.55s ± 2%  -7.03%  (p=0.000 n=20+20)

This increases the fannkuch function size from 801 bytes to 831 bytes,
but that is still smaller than Go 1.8.1 at 844 bytes.

It generally increases binary size a tiny amount.
Negligible compiler performance impact.

For the code in #14758:

name   old time/op    new time/op    delta
Foo-8     326ns ± 3%     312ns ± 3%  -4.32%  (p=0.000 n=28+30)
Bar-8     560ns ± 2%     565ns ± 2%  +0.96%  (p=0.002 n=30+27)

Updates #18977

name        old alloc/op      new alloc/op      delta
Template         38.8MB ± 0%       38.8MB ± 0%    ~     (p=0.690 n=5+5)
Unicode          28.7MB ± 0%       28.7MB ± 0%    ~     (p=0.841 n=5+5)
GoTypes           109MB ± 0%        109MB ± 0%    ~     (p=0.690 n=5+5)
Compiler          457MB ± 0%        457MB ± 0%    ~     (p=0.841 n=5+5)
SSA              1.10GB ± 0%       1.10GB ± 0%  +0.03%  (p=0.032 n=5+5)
Flate            24.4MB ± 0%       24.5MB ± 0%    ~     (p=0.690 n=5+5)
GoParser         30.9MB ± 0%       30.9MB ± 0%    ~     (p=0.421 n=5+5)
Reflect          73.3MB ± 0%       73.3MB ± 0%    ~     (p=1.000 n=5+5)
Tar              25.5MB ± 0%       25.5MB ± 0%    ~     (p=0.095 n=5+5)
XML              40.8MB ± 0%       40.9MB ± 0%    ~     (p=0.056 n=5+5)
[Geo mean]       71.6MB            71.6MB       +0.01%

name        old allocs/op     new allocs/op     delta
Template           395k ± 0%         394k ± 1%    ~     (p=1.000 n=5+5)
Unicode            344k ± 0%         344k ± 0%    ~     (p=0.690 n=5+5)
GoTypes           1.16M ± 0%        1.16M ± 0%    ~     (p=0.421 n=5+5)
Compiler          4.41M ± 0%        4.41M ± 0%    ~     (p=0.841 n=5+5)
SSA               9.79M ± 0%        9.79M ± 0%    ~     (p=0.310 n=5+5)
Flate              237k ± 0%         237k ± 0%    ~     (p=0.841 n=5+5)
GoParser           321k ± 0%         321k ± 1%    ~     (p=0.421 n=5+5)
Reflect            956k ± 0%         956k ± 0%    ~     (p=1.000 n=5+5)
Tar                251k ± 1%         252k ± 0%    ~     (p=0.095 n=5+5)
XML                399k ± 0%         400k ± 0%    ~     (p=0.222 n=5+5)
[Geo mean]         741k              741k       +0.03%

name        old object-bytes  new object-bytes  delta
Template           386k ± 0%         386k ± 0%  +0.05%  (p=0.008 n=5+5)
Unicode            202k ± 0%         202k ± 0%  +0.02%  (p=0.008 n=5+5)
GoTypes           1.16M ± 0%        1.16M ± 0%  +0.07%  (p=0.008 n=5+5)
Compiler          3.91M ± 0%        3.91M ± 0%  +0.05%  (p=0.008 n=5+5)
SSA               7.86M ± 0%        7.87M ± 0%  +0.07%  (p=0.008 n=5+5)
Flate              227k ± 0%         227k ± 0%  +0.10%  (p=0.008 n=5+5)
GoParser           283k ± 0%         283k ± 0%  +0.04%  (p=0.008 n=5+5)
Reflect            950k ± 0%         951k ± 0%  +0.04%  (p=0.008 n=5+5)
Tar                187k ± 0%         187k ± 0%  -0.03%  (p=0.008 n=5+5)
XML                406k ± 0%         406k ± 0%  +0.04%  (p=0.008 n=5+5)
[Geo mean]         647k              647k       +0.04%

Change-Id: I2015aa26338b90cf41e47f89564e336dc02608df
Reviewed-on: https://go-review.googlesource.com/43293
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/ssa/layout.go

index 55454445c3da76f9795b6d3f69293fe0a0277bc2..a2d4785e52bd9d79e457a876a2de3cbbbe3e9d90 100644 (file)
@@ -16,10 +16,18 @@ func layout(f *Func) {
        defer f.retSparseSet(posdegree)
        zerodegree := f.newSparseSet(f.NumBlocks()) // blocks with zero remaining degree
        defer f.retSparseSet(zerodegree)
+       exit := f.newSparseSet(f.NumBlocks()) // exit blocks
+       defer f.retSparseSet(exit)
 
        // Initialize indegree of each block
        for _, b := range f.Blocks {
                idToBlock[b.ID] = b
+               if b.Kind == BlockExit {
+                       // exit blocks are always scheduled last
+                       // TODO: also add blocks post-dominated by exit blocks
+                       exit.add(b.ID)
+                       continue
+               }
                indegree[b.ID] = len(b.Preds)
                if len(b.Preds) == 0 {
                        zerodegree.add(b.ID)
@@ -69,7 +77,7 @@ blockloop:
                mindegree := f.NumBlocks()
                for _, e := range order[len(order)-1].Succs {
                        c := e.b
-                       if scheduled[c.ID] {
+                       if scheduled[c.ID] || c.Kind == BlockExit {
                                continue
                        }
                        if indegree[c.ID] < mindegree {
@@ -90,14 +98,23 @@ blockloop:
                                continue blockloop
                        }
                }
-               // Still nothing, pick any block.
-               for {
+               // Still nothing, pick any non-exit block.
+               for posdegree.size() > 0 {
                        cid := posdegree.pop()
                        if !scheduled[cid] {
                                bid = cid
                                continue blockloop
                        }
                }
+               // Pick any exit block.
+               // TODO: Order these to minimize jump distances?
+               for {
+                       cid := exit.pop()
+                       if !scheduled[cid] {
+                               bid = cid
+                               continue blockloop
+                       }
+               }
        }
        f.Blocks = order
 }