2015-03-03 13:38:14 -08:00
|
|
|
// 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
|
|
|
|
|
|
2015-07-30 10:28:57 -07:00
|
|
|
import (
|
2015-08-10 19:00:34 -05:00
|
|
|
"fmt"
|
2015-07-30 10:28:57 -07:00
|
|
|
"log"
|
2016-03-17 14:12:12 -04:00
|
|
|
"regexp"
|
2015-07-30 10:28:57 -07:00
|
|
|
"runtime"
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
"strings"
|
2015-08-10 19:00:34 -05:00
|
|
|
"time"
|
2015-07-30 10:28:57 -07:00
|
|
|
)
|
2015-03-03 13:38:14 -08:00
|
|
|
|
|
|
|
|
// Compile is the main entry point for this package.
|
|
|
|
|
// Compile modifies f so that on return:
|
|
|
|
|
// · all Values in f map to 0 or 1 assembly instructions of the target architecture
|
|
|
|
|
// · the order of f.Blocks is the order to emit the Blocks
|
|
|
|
|
// · the order of b.Values is the order to emit the Values in each Block
|
|
|
|
|
// · f has a non-nil regAlloc field
|
|
|
|
|
func Compile(f *Func) {
|
|
|
|
|
// TODO: debugging - set flags to control verbosity of compiler,
|
|
|
|
|
// which phases to dump IR before/after, etc.
|
2016-01-29 14:44:15 -05:00
|
|
|
if f.Log() {
|
|
|
|
|
f.Logf("compiling %s\n", f.Name)
|
|
|
|
|
}
|
2015-03-03 13:38:14 -08:00
|
|
|
|
|
|
|
|
// hook to print function & phase if panic happens
|
|
|
|
|
phaseName := "init"
|
|
|
|
|
defer func() {
|
|
|
|
|
if phaseName != "" {
|
2015-07-30 10:28:57 -07:00
|
|
|
err := recover()
|
|
|
|
|
stack := make([]byte, 16384)
|
|
|
|
|
n := runtime.Stack(stack, false)
|
|
|
|
|
stack = stack[:n]
|
|
|
|
|
f.Fatalf("panic during %s while compiling %s:\n\n%v\n\n%s\n", phaseName, f.Name, err, stack)
|
2015-03-03 13:38:14 -08:00
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// Run all the passes
|
|
|
|
|
printFunc(f)
|
2015-08-10 12:15:52 -07:00
|
|
|
f.Config.HTML.WriteFunc("start", f)
|
2016-03-03 22:06:57 -08:00
|
|
|
if checkEnabled {
|
|
|
|
|
checkFunc(f)
|
|
|
|
|
}
|
2015-08-10 19:00:34 -05:00
|
|
|
const logMemStats = false
|
2015-03-03 13:38:14 -08:00
|
|
|
for _, p := range passes {
|
2016-02-29 10:43:18 -05:00
|
|
|
if !f.Config.optimize && !p.required || p.disabled {
|
2016-01-27 16:47:23 -08:00
|
|
|
continue
|
|
|
|
|
}
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
f.pass = &p
|
2015-03-03 13:38:14 -08:00
|
|
|
phaseName = p.name
|
2016-01-29 14:44:15 -05:00
|
|
|
if f.Log() {
|
|
|
|
|
f.Logf(" pass %s begin\n", p.name)
|
|
|
|
|
}
|
2015-08-10 12:15:52 -07:00
|
|
|
// TODO: capture logging during this pass, add it to the HTML
|
2015-08-10 19:00:34 -05:00
|
|
|
var mStart runtime.MemStats
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
if logMemStats || p.mem {
|
2015-08-10 19:00:34 -05:00
|
|
|
runtime.ReadMemStats(&mStart)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tStart := time.Now()
|
2015-03-03 13:38:14 -08:00
|
|
|
p.fn(f)
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
tEnd := time.Now()
|
2015-08-10 19:00:34 -05:00
|
|
|
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
// Need something less crude than "Log the whole intermediate result".
|
2016-01-30 17:37:38 -05:00
|
|
|
if f.Log() || f.Config.HTML != nil {
|
|
|
|
|
time := tEnd.Sub(tStart).Nanoseconds()
|
|
|
|
|
var stats string
|
|
|
|
|
if logMemStats {
|
|
|
|
|
var mEnd runtime.MemStats
|
|
|
|
|
runtime.ReadMemStats(&mEnd)
|
|
|
|
|
nBytes := mEnd.TotalAlloc - mStart.TotalAlloc
|
|
|
|
|
nAllocs := mEnd.Mallocs - mStart.Mallocs
|
|
|
|
|
stats = fmt.Sprintf("[%d ns %d allocs %d bytes]", time, nAllocs, nBytes)
|
|
|
|
|
} else {
|
|
|
|
|
stats = fmt.Sprintf("[%d ns]", time)
|
|
|
|
|
}
|
2015-08-10 19:00:34 -05:00
|
|
|
|
2016-01-29 14:44:15 -05:00
|
|
|
f.Logf(" pass %s end %s\n", p.name, stats)
|
2016-01-30 17:37:38 -05:00
|
|
|
printFunc(f)
|
2016-01-29 14:44:15 -05:00
|
|
|
f.Config.HTML.WriteFunc(fmt.Sprintf("after %s <span class=\"stats\">%s</span>", phaseName, stats), f)
|
|
|
|
|
}
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
if p.time || p.mem {
|
|
|
|
|
// Surround timing information w/ enough context to allow comparisons.
|
|
|
|
|
time := tEnd.Sub(tStart).Nanoseconds()
|
|
|
|
|
if p.time {
|
|
|
|
|
f.logStat("TIME(ns)", time)
|
|
|
|
|
}
|
|
|
|
|
if p.mem {
|
|
|
|
|
var mEnd runtime.MemStats
|
|
|
|
|
runtime.ReadMemStats(&mEnd)
|
|
|
|
|
nBytes := mEnd.TotalAlloc - mStart.TotalAlloc
|
|
|
|
|
nAllocs := mEnd.Mallocs - mStart.Mallocs
|
|
|
|
|
f.logStat("TIME(ns):BYTES:ALLOCS", time, nBytes, nAllocs)
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-03-03 22:06:57 -08:00
|
|
|
if checkEnabled {
|
|
|
|
|
checkFunc(f)
|
|
|
|
|
}
|
2015-03-03 13:38:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Squash error printing defer
|
|
|
|
|
phaseName = ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type pass struct {
|
2016-01-27 16:47:23 -08:00
|
|
|
name string
|
|
|
|
|
fn func(*Func)
|
|
|
|
|
required bool
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
disabled bool
|
|
|
|
|
time bool // report time to run pass
|
|
|
|
|
mem bool // report mem stats to run pass
|
|
|
|
|
stats int // pass reports own "stats" (e.g., branches removed)
|
|
|
|
|
debug int // pass performs some debugging. =1 should be in error-testing-friendly Warnl format.
|
|
|
|
|
test int // pass-specific ad-hoc option, perhaps useful in development
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-03 22:06:57 -08:00
|
|
|
// Run consistency checker between each phase
|
2016-03-15 15:00:57 -07:00
|
|
|
var checkEnabled = false
|
2016-03-03 22:06:57 -08:00
|
|
|
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
// PhaseOption sets the specified flag in the specified ssa phase,
|
|
|
|
|
// returning empty string if this was successful or a string explaining
|
2016-03-17 14:12:12 -04:00
|
|
|
// the error if it was not.
|
|
|
|
|
// A version of the phase name with "_" replaced by " " is also checked for a match.
|
|
|
|
|
// If the phase name begins a '~' then the rest of the underscores-replaced-with-blanks
|
|
|
|
|
// version is used as a regular expression to match the phase name(s).
|
|
|
|
|
//
|
|
|
|
|
// Special cases that have turned out to be useful:
|
|
|
|
|
// ssa/check/on enables checking after each phase
|
|
|
|
|
// ssa/all/time enables time reporting for all phases
|
|
|
|
|
//
|
|
|
|
|
// See gc/lex.go for dissection of the option string.
|
|
|
|
|
// Example uses:
|
|
|
|
|
//
|
|
|
|
|
// GO_GCFLAGS=-d=ssa/generic_cse/time,ssa/generic_cse/stats,ssa/generic_cse/debug=3 ./make.bash
|
|
|
|
|
//
|
|
|
|
|
// BOOT_GO_GCFLAGS=-d='ssa/~^.*scc$/off' GO_GCFLAGS='-d=ssa/~^.*scc$/off' ./make.bash
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
//
|
|
|
|
|
func PhaseOption(phase, flag string, val int) string {
|
2016-03-03 22:06:57 -08:00
|
|
|
if phase == "check" && flag == "on" {
|
|
|
|
|
checkEnabled = val != 0
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
if phase == "check" && flag == "off" {
|
|
|
|
|
checkEnabled = val == 0
|
|
|
|
|
return ""
|
|
|
|
|
}
|
2016-03-17 14:12:12 -04:00
|
|
|
|
|
|
|
|
alltime := false
|
|
|
|
|
if phase == "all" {
|
|
|
|
|
if flag == "time" {
|
|
|
|
|
alltime = val != 0
|
|
|
|
|
} else {
|
|
|
|
|
return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
underphase := strings.Replace(phase, "_", " ", -1)
|
2016-03-17 14:12:12 -04:00
|
|
|
var re *regexp.Regexp
|
|
|
|
|
if phase[0] == '~' {
|
|
|
|
|
r, ok := regexp.Compile(underphase[1:])
|
|
|
|
|
if ok != nil {
|
|
|
|
|
return fmt.Sprintf("Error %s in regexp for phase %s, flag %s", ok.Error(), phase, flag)
|
|
|
|
|
}
|
|
|
|
|
re = r
|
|
|
|
|
}
|
|
|
|
|
matchedOne := false
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
for i, p := range passes {
|
2016-03-17 14:12:12 -04:00
|
|
|
if phase == "all" {
|
|
|
|
|
p.time = alltime
|
|
|
|
|
passes[i] = p
|
|
|
|
|
matchedOne = true
|
|
|
|
|
} else if p.name == phase || p.name == underphase || re != nil && re.MatchString(p.name) {
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
switch flag {
|
|
|
|
|
case "on":
|
|
|
|
|
p.disabled = val == 0
|
|
|
|
|
case "off":
|
|
|
|
|
p.disabled = val != 0
|
|
|
|
|
case "time":
|
|
|
|
|
p.time = val != 0
|
|
|
|
|
case "mem":
|
|
|
|
|
p.mem = val != 0
|
|
|
|
|
case "debug":
|
|
|
|
|
p.debug = val
|
|
|
|
|
case "stats":
|
|
|
|
|
p.stats = val
|
|
|
|
|
case "test":
|
|
|
|
|
p.test = val
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase)
|
|
|
|
|
}
|
|
|
|
|
if p.disabled && p.required {
|
|
|
|
|
return fmt.Sprintf("Cannot disable required SSA phase %s using -d=ssa/%s debug option", phase, phase)
|
|
|
|
|
}
|
|
|
|
|
passes[i] = p
|
2016-03-17 14:12:12 -04:00
|
|
|
matchedOne = true
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
}
|
|
|
|
|
}
|
2016-03-17 14:12:12 -04:00
|
|
|
if matchedOne {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
return fmt.Sprintf("Did not find a phase matching %s in -d=ssa/... debug option", phase)
|
2015-03-03 13:38:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// list of passes for the compiler
|
|
|
|
|
var passes = [...]pass{
|
2016-01-14 16:02:23 -08:00
|
|
|
// TODO: combine phielim and copyelim into a single pass?
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
{name: "early phielim", fn: phielim},
|
|
|
|
|
{name: "early copyelim", fn: copyelim},
|
|
|
|
|
{name: "early deadcode", fn: deadcode}, // remove generated dead code to avoid doing pointless work during opt
|
|
|
|
|
{name: "short circuit", fn: shortcircuit},
|
|
|
|
|
{name: "decompose user", fn: decomposeUser, required: true},
|
|
|
|
|
{name: "opt", fn: opt, required: true}, // TODO: split required rules and optimizing rules
|
|
|
|
|
{name: "zero arg cse", fn: zcse, required: true}, // required to merge OpSB values
|
|
|
|
|
{name: "opt deadcode", fn: deadcode}, // remove any blocks orphaned during opt
|
|
|
|
|
{name: "generic cse", fn: cse},
|
2016-02-29 19:29:04 +01:00
|
|
|
{name: "phiopt", fn: phiopt},
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
{name: "nilcheckelim", fn: nilcheckelim},
|
2016-02-19 12:14:42 +01:00
|
|
|
{name: "prove", fn: prove},
|
2016-03-11 01:10:35 +01:00
|
|
|
{name: "decompose builtin", fn: decomposeBuiltIn, required: true},
|
2016-03-03 11:13:43 +01:00
|
|
|
{name: "dec", fn: dec, required: true},
|
2016-03-14 19:11:19 +01:00
|
|
|
{name: "late opt", fn: opt, required: true}, // TODO: split required rules and optimizing rules
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
{name: "generic deadcode", fn: deadcode},
|
|
|
|
|
{name: "fuse", fn: fuse},
|
|
|
|
|
{name: "dse", fn: dse},
|
|
|
|
|
{name: "tighten", fn: tighten}, // move values closer to their uses
|
|
|
|
|
{name: "lower", fn: lower, required: true},
|
|
|
|
|
{name: "lowered cse", fn: cse},
|
|
|
|
|
{name: "lowered deadcode", fn: deadcode, required: true},
|
|
|
|
|
{name: "checkLower", fn: checkLower, required: true},
|
|
|
|
|
{name: "late phielim", fn: phielim},
|
|
|
|
|
{name: "late copyelim", fn: copyelim},
|
|
|
|
|
{name: "late deadcode", fn: deadcode},
|
2016-02-27 11:54:52 -05:00
|
|
|
{name: "critical", fn: critical, required: true}, // remove critical edges
|
|
|
|
|
{name: "likelyadjust", fn: likelyadjust},
|
[dev.ssa] cmd/compile: enhance command line option processing for SSA
The -d compiler flag can also specify ssa phase and flag,
for example -d=ssa/generic_cse/time,ssa/generic_cse/stats
Spaces in the phase names can be specified with an
underscore. Flags currently parsed (not necessarily
recognized by the phases yet) are:
on, off, mem, time, debug, stats, and test
On, off and time are handled in the harness,
debug, stats, and test are interpreted by the phase itself.
The pass is now attached to the Func being compiled, and a
new method logStats(key, ...value) on *Func to encourage a
semi-standardized format for that output. Output fields
are separated by tabs to ease digestion by awk and
spreadsheets. For example,
if f.pass.stats > 0 {
f.logStat("CSE REWRITES", rewrites)
}
Change-Id: I16db2b5af64c50ca9a47efeb51d961147a903abc
Reviewed-on: https://go-review.googlesource.com/19885
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
2016-02-25 13:10:51 -05:00
|
|
|
{name: "layout", fn: layout, required: true}, // schedule blocks
|
|
|
|
|
{name: "schedule", fn: schedule, required: true}, // schedule values
|
|
|
|
|
{name: "flagalloc", fn: flagalloc, required: true}, // allocate flags register
|
|
|
|
|
{name: "regalloc", fn: regalloc, required: true}, // allocate int & float registers + stack slots
|
|
|
|
|
{name: "trim", fn: trim}, // remove empty blocks
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Double-check phase ordering constraints.
|
|
|
|
|
// This code is intended to document the ordering requirements
|
2016-03-01 23:21:55 +00:00
|
|
|
// between different phases. It does not override the passes
|
2015-03-23 17:02:11 -07:00
|
|
|
// list above.
|
2015-05-05 16:19:12 -07:00
|
|
|
type constraint struct {
|
|
|
|
|
a, b string // a must come before b
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var passOrder = [...]constraint{
|
2016-02-19 12:14:42 +01:00
|
|
|
// prove reliese on common-subexpression elimination for maximum benefits.
|
|
|
|
|
{"generic cse", "prove"},
|
|
|
|
|
// deadcode after prove to eliminate all new dead blocks.
|
|
|
|
|
{"prove", "generic deadcode"},
|
2015-05-26 14:43:25 -07:00
|
|
|
// common-subexpression before dead-store elim, so that we recognize
|
|
|
|
|
// when two address expressions are the same.
|
|
|
|
|
{"generic cse", "dse"},
|
2015-06-03 12:31:47 -07:00
|
|
|
// cse substantially improves nilcheckelim efficacy
|
|
|
|
|
{"generic cse", "nilcheckelim"},
|
|
|
|
|
// allow deadcode to clean up after nilcheckelim
|
|
|
|
|
{"nilcheckelim", "generic deadcode"},
|
|
|
|
|
// nilcheckelim generates sequences of plain basic blocks
|
|
|
|
|
{"nilcheckelim", "fuse"},
|
2015-08-30 21:19:20 -05:00
|
|
|
// nilcheckelim relies on opt to rewrite user nil checks
|
|
|
|
|
{"opt", "nilcheckelim"},
|
[dev.ssa] cmd/compile: add SSA pass to move values closer to uses
Even this very simple, restricted initial implementation helps.
While running make.bash, it moves 84437 values
to new, closer homes.
As a concrete example:
func f_ssa(i, j int, b bool) int {
if !b {
return 0
}
return i + j
}
It cuts off one stack slot and two instructions:
Before:
"".f_ssa t=1 size=96 value=0 args=0x20 locals=0x18
0x0000 00000 (x.go:3) TEXT "".f_ssa(SB), $24-32
0x0000 00000 (x.go:3) SUBQ $24, SP
0x0004 00004 (x.go:3) FUNCDATA $0, "".gcargs·0(SB)
0x0004 00004 (x.go:3) FUNCDATA $1, "".gclocals·1(SB)
0x0004 00004 (x.go:5) MOVQ $0, AX
0x0006 00006 (x.go:3) MOVQ 32(SP), CX
0x000b 00011 (x.go:3) MOVQ 40(SP), DX
0x0010 00016 (x.go:3) LEAQ 48(SP), BX
0x0015 00021 (x.go:3) MOVB (BX), BPB
0x0018 00024 (x.go:3) MOVQ $0, SI
0x001a 00026 (x.go:3) MOVQ SI, 56(SP)
0x001f 00031 (x.go:3) TESTB BPB, BPB
0x0022 00034 (x.go:5) MOVQ AX, (SP)
0x0026 00038 (x.go:3) MOVQ CX, 8(SP)
0x002b 00043 (x.go:3) MOVQ DX, 16(SP)
0x0030 00048 (x.go:4) JEQ 74
0x0032 00050 (x.go:3) MOVQ 8(SP), AX
0x0037 00055 (x.go:3) MOVQ 16(SP), CX
0x003c 00060 (x.go:7) LEAQ (AX)(CX*1), DX
0x0040 00064 (x.go:7) MOVQ DX, 56(SP)
0x0045 00069 (x.go:3) ADDQ $24, SP
0x0049 00073 (x.go:3) RET
0x004a 00074 (x.go:5) MOVQ (SP), AX
0x004e 00078 (x.go:5) MOVQ AX, 56(SP)
0x0053 00083 (x.go:3) JMP 69
After:
"".f_ssa t=1 size=80 value=0 args=0x20 locals=0x10
0x0000 00000 (x.go:3) TEXT "".f_ssa(SB), $16-32
0x0000 00000 (x.go:3) SUBQ $16, SP
0x0004 00004 (x.go:3) FUNCDATA $0, "".gcargs·0(SB)
0x0004 00004 (x.go:3) FUNCDATA $1, "".gclocals·1(SB)
0x0004 00004 (x.go:3) MOVQ 32(SP), AX
0x0009 00009 (x.go:3) MOVQ 24(SP), CX
0x000e 00014 (x.go:3) LEAQ 40(SP), DX
0x0013 00019 (x.go:3) MOVB (DX), BL
0x0015 00021 (x.go:3) MOVQ $0, BP
0x0017 00023 (x.go:3) MOVQ BP, 48(SP)
0x001c 00028 (x.go:3) TESTB BL, BL
0x001e 00030 (x.go:3) MOVQ AX, (SP)
0x0022 00034 (x.go:3) MOVQ CX, 8(SP)
0x0027 00039 (x.go:4) JEQ 64
0x0029 00041 (x.go:3) MOVQ 8(SP), AX
0x002e 00046 (x.go:3) MOVQ (SP), CX
0x0032 00050 (x.go:7) LEAQ (AX)(CX*1), DX
0x0036 00054 (x.go:7) MOVQ DX, 48(SP)
0x003b 00059 (x.go:3) ADDQ $16, SP
0x003f 00063 (x.go:3) RET
0x0040 00064 (x.go:5) MOVQ $0, AX
0x0042 00066 (x.go:5) MOVQ AX, 48(SP)
0x0047 00071 (x.go:3) JMP 59
Of course, the old backend is still well ahead:
"".f_ssa t=1 size=48 value=0 args=0x20 locals=0x0
0x0000 00000 (x.go:3) TEXT "".f_ssa(SB), $0-32
0x0000 00000 (x.go:3) NOP
0x0000 00000 (x.go:3) NOP
0x0000 00000 (x.go:3) FUNCDATA $0, gclocals·a8eabfc4a4514ed6b3b0c61e9680e440(SB)
0x0000 00000 (x.go:3) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0000 00000 (x.go:4) CMPB "".b+24(FP), $0
0x0005 00005 (x.go:4) JNE 17
0x0007 00007 (x.go:5) MOVQ $0, "".~r3+32(FP)
0x0010 00016 (x.go:5) RET
0x0011 00017 (x.go:7) MOVQ "".i+8(FP), BX
0x0016 00022 (x.go:7) MOVQ "".j+16(FP), BP
0x001b 00027 (x.go:7) ADDQ BP, BX
0x001e 00030 (x.go:7) MOVQ BX, "".~r3+32(FP)
0x0023 00035 (x.go:7) RET
Some regalloc improvements should help considerably.
Change-Id: I95bb5dd83e56afd70ae4e983f1d32dffd0c3d46a
Reviewed-on: https://go-review.googlesource.com/13142
Reviewed-by: Keith Randall <khr@golang.org>
2015-08-04 14:55:35 -07:00
|
|
|
// tighten should happen before lowering to avoid splitting naturally paired instructions such as CMP/SET
|
|
|
|
|
{"tighten", "lower"},
|
|
|
|
|
// tighten will be most effective when as many values have been removed as possible
|
|
|
|
|
{"generic deadcode", "tighten"},
|
|
|
|
|
{"generic cse", "tighten"},
|
2016-02-08 11:00:43 -08:00
|
|
|
// don't run optimization pass until we've decomposed builtin objects
|
2016-03-11 01:10:35 +01:00
|
|
|
{"decompose builtin", "late opt"},
|
2015-03-23 17:02:11 -07:00
|
|
|
// don't layout blocks until critical edges have been removed
|
2015-05-05 16:19:12 -07:00
|
|
|
{"critical", "layout"},
|
2015-03-23 17:02:11 -07:00
|
|
|
// regalloc requires the removal of all critical edges
|
2015-05-05 16:19:12 -07:00
|
|
|
{"critical", "regalloc"},
|
2015-03-23 17:02:11 -07:00
|
|
|
// regalloc requires all the values in a block to be scheduled
|
2015-05-05 16:19:12 -07:00
|
|
|
{"schedule", "regalloc"},
|
2015-08-04 15:47:22 -07:00
|
|
|
// checkLower must run after lowering & subsequent dead code elim
|
|
|
|
|
{"lower", "checkLower"},
|
|
|
|
|
{"lowered deadcode", "checkLower"},
|
2015-12-09 15:58:18 -08:00
|
|
|
// flagalloc needs instructions to be scheduled.
|
|
|
|
|
{"schedule", "flagalloc"},
|
|
|
|
|
// regalloc needs flags to be allocated first.
|
|
|
|
|
{"flagalloc", "regalloc"},
|
2016-01-21 13:27:01 -08:00
|
|
|
// trim needs regalloc to be done first.
|
|
|
|
|
{"regalloc", "trim"},
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func init() {
|
2015-05-05 16:19:12 -07:00
|
|
|
for _, c := range passOrder {
|
|
|
|
|
a, b := c.a, c.b
|
2015-03-23 17:02:11 -07:00
|
|
|
i := -1
|
|
|
|
|
j := -1
|
|
|
|
|
for k, p := range passes {
|
|
|
|
|
if p.name == a {
|
|
|
|
|
i = k
|
|
|
|
|
}
|
|
|
|
|
if p.name == b {
|
|
|
|
|
j = k
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if i < 0 {
|
|
|
|
|
log.Panicf("pass %s not found", a)
|
|
|
|
|
}
|
|
|
|
|
if j < 0 {
|
|
|
|
|
log.Panicf("pass %s not found", b)
|
|
|
|
|
}
|
|
|
|
|
if i >= j {
|
|
|
|
|
log.Panicf("passes %s and %s out of order", a, b)
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-03 13:38:14 -08:00
|
|
|
}
|