mirror of
https://github.com/golang/go
synced 2024-10-05 11:41:22 -06:00
[dev.ssa] cmd/compile: change ssa compilation trigger
We used to compile everything with SSA and then decide whether to use the result or not. It was useful when we were working on coverage without much regard for correctness, but not so much now. Instead, let's decide what we're going to compile and go through the SSA compiler for only those functions. TODO: next CL: get rid of all the UnimplementedF stuff. Change-Id: If629addd8b62cd38ef553fd5d835114137885ce0 Reviewed-on: https://go-review.googlesource.com/17763 Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
4989337192
commit
5b355a7907
@ -364,7 +364,6 @@ func compile(fn *Node) {
|
|||||||
var gcargs *Sym
|
var gcargs *Sym
|
||||||
var gclocals *Sym
|
var gclocals *Sym
|
||||||
var ssafn *ssa.Func
|
var ssafn *ssa.Func
|
||||||
var usessa bool
|
|
||||||
if fn.Nbody == nil {
|
if fn.Nbody == nil {
|
||||||
if pure_go != 0 || strings.HasPrefix(fn.Func.Nname.Sym.Name, "init.") {
|
if pure_go != 0 || strings.HasPrefix(fn.Func.Nname.Sym.Name, "init.") {
|
||||||
Yyerror("missing function body for %q", fn.Func.Nname.Sym.Name)
|
Yyerror("missing function body for %q", fn.Func.Nname.Sym.Name)
|
||||||
@ -417,9 +416,8 @@ func compile(fn *Node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build an SSA backend function.
|
// Build an SSA backend function.
|
||||||
// TODO: get rid of usessa.
|
if shouldssa(Curfn) {
|
||||||
if Thearch.Thestring == "amd64" {
|
ssafn = buildssa(Curfn)
|
||||||
ssafn, usessa = buildssa(Curfn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continpc = nil
|
continpc = nil
|
||||||
@ -485,7 +483,7 @@ func compile(fn *Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ssafn != nil && usessa {
|
if ssafn != nil {
|
||||||
genssa(ssafn, ptxt, gcargs, gclocals)
|
genssa(ssafn, ptxt, gcargs, gclocals)
|
||||||
if Curfn.Func.Endlineno != 0 {
|
if Curfn.Func.Endlineno != 0 {
|
||||||
lineno = Curfn.Func.Endlineno
|
lineno = Curfn.Func.Endlineno
|
||||||
|
@ -21,14 +21,10 @@ import (
|
|||||||
// Smallest possible faulting page at address zero.
|
// Smallest possible faulting page at address zero.
|
||||||
const minZeroPage = 4096
|
const minZeroPage = 4096
|
||||||
|
|
||||||
// buildssa builds an SSA function
|
func shouldssa(fn *Node) bool {
|
||||||
// and reports whether it should be used.
|
if Thearch.Thestring != "amd64" {
|
||||||
// Once the SSA implementation is complete,
|
return false
|
||||||
// it will never return nil, and the bool can be removed.
|
}
|
||||||
func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
|
|
||||||
name := fn.Func.Nname.Sym.Name
|
|
||||||
gossahash := os.Getenv("GOSSAHASH")
|
|
||||||
usessa = strings.HasSuffix(name, "_ssa") || strings.Contains(name, "_ssa.") || name == os.Getenv("GOSSAFUNC")
|
|
||||||
|
|
||||||
// Environment variable control of SSA CG
|
// Environment variable control of SSA CG
|
||||||
// 1. IF GOSSAFUNC == current function name THEN
|
// 1. IF GOSSAFUNC == current function name THEN
|
||||||
@ -54,7 +50,63 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
|
|||||||
// GOSSAHASH to n or N, or selectively with strings of
|
// GOSSAHASH to n or N, or selectively with strings of
|
||||||
// 0 and 1.
|
// 0 and 1.
|
||||||
|
|
||||||
if usessa {
|
name := fn.Func.Nname.Sym.Name
|
||||||
|
|
||||||
|
funcname := os.Getenv("GOSSAFUNC")
|
||||||
|
if funcname != "" {
|
||||||
|
// If GOSSAFUNC is set, compile only that function.
|
||||||
|
return name == funcname
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg := os.Getenv("GOSSAPKG")
|
||||||
|
if pkg != "" {
|
||||||
|
// If GOSSAPKG is set, compile only that package.
|
||||||
|
return localpkg.Name == pkg
|
||||||
|
}
|
||||||
|
|
||||||
|
gossahash := os.Getenv("GOSSAHASH")
|
||||||
|
if gossahash == "" || gossahash == "y" || gossahash == "Y" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if gossahash == "n" || gossahash == "N" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the hash of the name against a partial input hash.
|
||||||
|
// We use this feature to do a binary search within a package to
|
||||||
|
// find a function that is incorrectly compiled.
|
||||||
|
hstr := ""
|
||||||
|
for _, b := range sha1.Sum([]byte(name)) {
|
||||||
|
hstr += fmt.Sprintf("%08b", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(hstr, gossahash) {
|
||||||
|
fmt.Printf("GOSSAHASH triggered %s\n", name)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iteratively try additional hashes to allow tests for multi-point
|
||||||
|
// failure.
|
||||||
|
for i := 0; true; i++ {
|
||||||
|
ev := fmt.Sprintf("GOSSAHASH%d", i)
|
||||||
|
evv := os.Getenv(ev)
|
||||||
|
if evv == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(hstr, evv) {
|
||||||
|
fmt.Printf("%s triggered %s\n", ev, name)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildssa builds an SSA function.
|
||||||
|
func buildssa(fn *Node) *ssa.Func {
|
||||||
|
name := fn.Func.Nname.Sym.Name
|
||||||
|
printssa := strings.HasSuffix(name, "_ssa") || strings.Contains(name, "_ssa.") || name == os.Getenv("GOSSAFUNC")
|
||||||
|
if printssa {
|
||||||
fmt.Println("generating SSA for", name)
|
fmt.Println("generating SSA for", name)
|
||||||
dumplist("buildssa-enter", fn.Func.Enter)
|
dumplist("buildssa-enter", fn.Func.Enter)
|
||||||
dumplist("buildssa-body", fn.Nbody)
|
dumplist("buildssa-body", fn.Nbody)
|
||||||
@ -68,7 +120,7 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
|
|||||||
// TODO(khr): build config just once at the start of the compiler binary
|
// TODO(khr): build config just once at the start of the compiler binary
|
||||||
|
|
||||||
var e ssaExport
|
var e ssaExport
|
||||||
e.log = usessa
|
e.log = printssa
|
||||||
s.config = ssa.NewConfig(Thearch.Thestring, &e, Ctxt)
|
s.config = ssa.NewConfig(Thearch.Thestring, &e, Ctxt)
|
||||||
s.f = s.config.NewFunc()
|
s.f = s.config.NewFunc()
|
||||||
s.f.Name = name
|
s.f.Name = name
|
||||||
@ -82,7 +134,7 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
|
|||||||
// TODO: generate and print a mapping from nodes to values and blocks
|
// TODO: generate and print a mapping from nodes to values and blocks
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if !usessa {
|
if !printssa {
|
||||||
s.config.HTML.Close()
|
s.config.HTML.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -170,7 +222,7 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if nerrors > 0 {
|
if nerrors > 0 {
|
||||||
return nil, false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link up variable uses to variable definitions
|
// Link up variable uses to variable definitions
|
||||||
@ -182,46 +234,7 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
|
|||||||
// Main call to ssa package to compile function
|
// Main call to ssa package to compile function
|
||||||
ssa.Compile(s.f)
|
ssa.Compile(s.f)
|
||||||
|
|
||||||
// gossahash = "y" is historical/symmetric-with-"n" -- i.e., not really needed.
|
return s.f
|
||||||
if usessa || gossahash == "" || gossahash == "y" || gossahash == "Y" {
|
|
||||||
return s.f, true
|
|
||||||
}
|
|
||||||
if gossahash == "n" || gossahash == "N" {
|
|
||||||
if localpkg.Name != os.Getenv("GOSSAPKG") {
|
|
||||||
return s.f, false
|
|
||||||
}
|
|
||||||
// Use everything in the package
|
|
||||||
return s.f, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the hash of the name against a partial input hash.
|
|
||||||
// We use this feature to do a binary search within a package to
|
|
||||||
// find a function that is incorrectly compiled.
|
|
||||||
hstr := ""
|
|
||||||
for _, b := range sha1.Sum([]byte(name)) {
|
|
||||||
hstr += fmt.Sprintf("%08b", b)
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasSuffix(hstr, gossahash) {
|
|
||||||
fmt.Printf("GOSSAHASH triggered %s\n", name)
|
|
||||||
return s.f, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iteratively try additional hashes to allow tests for multi-point
|
|
||||||
// failure.
|
|
||||||
for i := 0; true; i++ {
|
|
||||||
ev := fmt.Sprintf("GOSSAHASH%d", i)
|
|
||||||
evv := os.Getenv(ev)
|
|
||||||
if evv == "" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(hstr, evv) {
|
|
||||||
fmt.Printf("%s triggered %s\n", ev, name)
|
|
||||||
return s.f, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.f, false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type state struct {
|
type state struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user