mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
cmd/compile: ignore all unreachable values during simple phi insertion
Simple phi insertion already had a heuristic to check for dead blocks, namely having no predecessors. When we stopped generating code for dead blocks, we eliminated some values contained in more subtle dead blocks, which confused phi insertion. Compensate by beefing up the reachability check. Fixes #19678 Change-Id: I0081e4a46f7ce2f69b131a34a0553874a0cb373e Reviewed-on: https://go-review.googlesource.com/38602 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
ad8c17b703
commit
e00e57d67c
|
@ -437,6 +437,8 @@ type simplePhiState struct {
|
|||
}
|
||||
|
||||
func (s *simplePhiState) insertPhis() {
|
||||
reachable := ssa.ReachableBlocks(s.f)
|
||||
|
||||
// Find FwdRef ops.
|
||||
for _, b := range s.f.Blocks {
|
||||
for _, v := range b.Values {
|
||||
|
@ -459,12 +461,12 @@ loop:
|
|||
s.fwdrefs = s.fwdrefs[:len(s.fwdrefs)-1]
|
||||
b := v.Block
|
||||
var_ := v.Aux.(*Node)
|
||||
if len(b.Preds) == 0 {
|
||||
if b == s.f.Entry {
|
||||
// No variable should be live at entry.
|
||||
s.s.Fatalf("Value live at entry. It shouldn't be. func %s, node %v, value %v", s.f.Name, var_, v)
|
||||
}
|
||||
// This block is dead; it has no predecessors and it is not the entry block.
|
||||
if b == s.f.Entry {
|
||||
// No variable should be live at entry.
|
||||
s.s.Fatalf("Value live at entry. It shouldn't be. func %s, node %v, value %v", s.f.Name, var_, v)
|
||||
}
|
||||
if !reachable[b.ID] {
|
||||
// This block is dead.
|
||||
// It doesn't matter what we use here as long as it is well-formed.
|
||||
v.Op = ssa.OpUnknown
|
||||
v.Aux = nil
|
||||
|
|
|
@ -6,13 +6,13 @@ package ssa
|
|||
|
||||
// findlive returns the reachable blocks and live values in f.
|
||||
func findlive(f *Func) (reachable []bool, live []bool) {
|
||||
reachable = reachableBlocks(f)
|
||||
reachable = ReachableBlocks(f)
|
||||
live = liveValues(f, reachable)
|
||||
return
|
||||
}
|
||||
|
||||
// reachableBlocks returns the reachable blocks in f.
|
||||
func reachableBlocks(f *Func) []bool {
|
||||
// ReachableBlocks returns the reachable blocks in f.
|
||||
func ReachableBlocks(f *Func) []bool {
|
||||
reachable := make([]bool, f.NumBlocks())
|
||||
reachable[f.Entry.ID] = true
|
||||
p := []*Block{f.Entry} // stack-like worklist
|
||||
|
@ -106,7 +106,7 @@ func deadcode(f *Func) {
|
|||
}
|
||||
|
||||
// Find reachable blocks.
|
||||
reachable := reachableBlocks(f)
|
||||
reachable := ReachableBlocks(f)
|
||||
|
||||
// Get rid of edges from dead to live code.
|
||||
for _, b := range f.Blocks {
|
||||
|
|
21
test/fixedbugs/issue19678.go
Normal file
21
test/fixedbugs/issue19678.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
// compile
|
||||
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Used to crash when compiling functions containing
|
||||
// forward refs in dead code.
|
||||
|
||||
package p
|
||||
|
||||
var f func(int)
|
||||
|
||||
func g() {
|
||||
l1:
|
||||
i := 0
|
||||
goto l1
|
||||
l2:
|
||||
f(i)
|
||||
goto l2
|
||||
}
|
Loading…
Reference in a new issue