]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: Deduplicate panic{index,slice,divide} calls
authorKeith Randall <khr@golang.org>
Tue, 10 Nov 2015 05:35:40 +0000 (21:35 -0800)
committerKeith Randall <khr@golang.org>
Tue, 10 Nov 2015 16:56:11 +0000 (16:56 +0000)
Panics are only distinguished by their type and line number, so
if we can trigger two of those panics in the same line, use the
same panic call.  For example, in a[i]+b[j] we need only one
panicindex call that both bounds checks can use.

Change-Id: Ia2b6d3b1a67f2775df05fb72b8a1b149833572b7
Reviewed-on: https://go-review.googlesource.com/16772
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/gc/ssa.go

index 90abd8e05d8025e9c44ee96f2c1bb1acbb026a99..0b674806fe10d5cf14ecd593fc737238859e048f 100644 (file)
@@ -73,6 +73,7 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
        s.f = s.config.NewFunc()
        s.f.Name = name
        s.exitCode = fn.Func.Exit
+       s.panics = map[funcLine]*ssa.Block{}
 
        if name == os.Getenv("GOSSAFUNC") {
                // TODO: tempfile? it is handy to have the location
@@ -270,6 +271,15 @@ type state struct {
 
        // line number stack.  The current line number is top of stack
        line []int32
+
+       // list of panic calls by function name and line number.
+       // Used to deduplicate panic calls.
+       panics map[funcLine]*ssa.Block
+}
+
+type funcLine struct {
+       f    *Node
+       line int32
 }
 
 type ssaLabel struct {
@@ -2517,14 +2527,18 @@ func (s *state) check(cmp *ssa.Value, fn *Node) {
        b.Control = cmp
        b.Likely = ssa.BranchLikely
        bNext := s.f.NewBlock(ssa.BlockPlain)
-       bPanic := s.f.NewBlock(ssa.BlockPlain)
+       line := s.peekLine()
+       bPanic := s.panics[funcLine{fn, line}]
+       if bPanic == nil {
+               bPanic = s.f.NewBlock(ssa.BlockPlain)
+               s.panics[funcLine{fn, line}] = bPanic
+               s.startBlock(bPanic)
+               // The panic call takes/returns memory to ensure that the right
+               // memory state is observed if the panic happens.
+               s.rtcall(fn, false, nil)
+       }
        b.AddEdgeTo(bNext)
        b.AddEdgeTo(bPanic)
-       s.startBlock(bPanic)
-       // The panic call takes/returns memory to ensure that the right
-       // memory state is observed if the panic happens.
-       s.rtcall(fn, false, nil)
-
        s.startBlock(bNext)
 }