go/src/cmd/compile/internal/ssa/print.go
Keith Randall b5c5efd5de [dev.ssa] cmd/compile: optimize phi ops
Redo how we keep track of forward references when building SSA.
When the forward reference is resolved, update the Value node
in place.

Improve the phi elimination pass so it can simplify phis of phis.

Give SSA package access to decoded line numbers.  Fix line numbers
for constant booleans.

Change-Id: I3dc9896148d260be2f3dd14cbe5db639ec9fa6b7
Reviewed-on: https://go-review.googlesource.com/18674
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
2016-01-20 21:45:37 +00:00

149 lines
2.9 KiB
Go

// Copyright 2015 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.
package ssa
import (
"bytes"
"fmt"
"io"
)
func printFunc(f *Func) {
f.Logf("%s", f)
}
func (f *Func) String() string {
var buf bytes.Buffer
p := stringFuncPrinter{w: &buf}
fprintFunc(p, f)
return buf.String()
}
type funcPrinter interface {
header(f *Func)
startBlock(b *Block, reachable bool)
endBlock(b *Block)
value(v *Value, live bool)
startDepCycle()
endDepCycle()
named(n LocalSlot, vals []*Value)
}
type stringFuncPrinter struct {
w io.Writer
}
func (p stringFuncPrinter) header(f *Func) {
fmt.Fprint(p.w, f.Name)
fmt.Fprint(p.w, " ")
fmt.Fprintln(p.w, f.Type)
}
func (p stringFuncPrinter) startBlock(b *Block, reachable bool) {
fmt.Fprintf(p.w, " b%d:", b.ID)
if len(b.Preds) > 0 {
io.WriteString(p.w, " <-")
for _, pred := range b.Preds {
fmt.Fprintf(p.w, " b%d", pred.ID)
}
}
if !reachable {
fmt.Fprint(p.w, " DEAD")
}
io.WriteString(p.w, "\n")
}
func (p stringFuncPrinter) endBlock(b *Block) {
fmt.Fprintln(p.w, " "+b.LongString())
}
func (p stringFuncPrinter) value(v *Value, live bool) {
fmt.Fprint(p.w, " ")
//fmt.Fprint(p.w, v.Block.Func.Config.fe.Line(v.Line))
//fmt.Fprint(p.w, ": ")
fmt.Fprint(p.w, v.LongString())
if !live {
fmt.Fprint(p.w, " DEAD")
}
fmt.Fprintln(p.w)
}
func (p stringFuncPrinter) startDepCycle() {
fmt.Fprintln(p.w, "dependency cycle!")
}
func (p stringFuncPrinter) endDepCycle() {}
func (p stringFuncPrinter) named(n LocalSlot, vals []*Value) {
fmt.Fprintf(p.w, "name %s: %v\n", n.Name(), vals)
}
func fprintFunc(p funcPrinter, f *Func) {
reachable, live := findlive(f)
p.header(f)
printed := make([]bool, f.NumValues())
for _, b := range f.Blocks {
p.startBlock(b, reachable[b.ID])
if f.scheduled {
// Order of Values has been decided - print in that order.
for _, v := range b.Values {
p.value(v, live[v.ID])
printed[v.ID] = true
}
p.endBlock(b)
continue
}
// print phis first since all value cycles contain a phi
n := 0
for _, v := range b.Values {
if v.Op != OpPhi {
continue
}
p.value(v, live[v.ID])
printed[v.ID] = true
n++
}
// print rest of values in dependency order
for n < len(b.Values) {
m := n
outer:
for _, v := range b.Values {
if printed[v.ID] {
continue
}
for _, w := range v.Args {
// w == nil shouldn't happen, but if it does,
// don't panic; we'll get a better diagnosis later.
if w != nil && w.Block == b && !printed[w.ID] {
continue outer
}
}
p.value(v, live[v.ID])
printed[v.ID] = true
n++
}
if m == n {
p.startDepCycle()
for _, v := range b.Values {
if printed[v.ID] {
continue
}
p.value(v, live[v.ID])
printed[v.ID] = true
n++
}
p.endDepCycle()
}
}
p.endBlock(b)
}
for name, vals := range f.NamedValues {
p.named(name, vals)
}
}