[dev.ssa] cmd/compile: Deduplicate panic{index,slice,divide} calls
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>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 90abd8e..0b67480 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -73,6 +73,7 @@
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 @@
// 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 @@
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)
}