Commit 4e95dfed authored by Todd Neal's avatar Todd Neal

[dev.ssa] cmd/compile: add max arg length to opcodes

Add the max arg length to opcodes and use it in zcse.  Doesn't affect
speed, but allows better checking in checkFunc and removes the need
to keep a list of zero arg opcodes up to date.

Change-Id: I157c6587154604119720ec6228b767b6e52bb5c7
Reviewed-on: https://go-review.googlesource.com/19994Reviewed-by: default avatarKeith Randall <khr@golang.org>
Run-TryBot: Todd Neal <todd@tneal.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 91f69c67
...@@ -148,6 +148,13 @@ func checkFunc(f *Func) { ...@@ -148,6 +148,13 @@ func checkFunc(f *Func) {
} }
for _, v := range b.Values { for _, v := range b.Values {
// Check to make sure argument count makes sense (argLen of -1 indicates
// variable length args)
nArgs := opcodeTable[v.Op].argLen
if nArgs != -1 && int32(len(v.Args)) != nArgs {
f.Fatalf("value %v has %d args, expected %d", v.LongString(),
len(v.Args), nArgs)
}
// Check to make sure aux values make sense. // Check to make sure aux values make sense.
canHaveAux := false canHaveAux := false
......
...@@ -14,7 +14,7 @@ func TestFuseEliminatesOneBranch(t *testing.T) { ...@@ -14,7 +14,7 @@ func TestFuseEliminatesOneBranch(t *testing.T) {
Goto("checkPtr")), Goto("checkPtr")),
Bloc("checkPtr", Bloc("checkPtr",
Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"), Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"), Valu("nilptr", OpConstNil, ptrType, 0, nil),
Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"), Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"),
If("bool1", "then", "exit")), If("bool1", "then", "exit")),
Bloc("then", Bloc("then",
...@@ -42,7 +42,7 @@ func TestFuseEliminatesBothBranches(t *testing.T) { ...@@ -42,7 +42,7 @@ func TestFuseEliminatesBothBranches(t *testing.T) {
Goto("checkPtr")), Goto("checkPtr")),
Bloc("checkPtr", Bloc("checkPtr",
Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"), Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"), Valu("nilptr", OpConstNil, ptrType, 0, nil),
Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"), Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"),
If("bool1", "then", "else")), If("bool1", "then", "else")),
Bloc("then", Bloc("then",
...@@ -75,7 +75,7 @@ func TestFuseHandlesPhis(t *testing.T) { ...@@ -75,7 +75,7 @@ func TestFuseHandlesPhis(t *testing.T) {
Goto("checkPtr")), Goto("checkPtr")),
Bloc("checkPtr", Bloc("checkPtr",
Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"), Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"), Valu("nilptr", OpConstNil, ptrType, 0, nil),
Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"), Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"),
If("bool1", "then", "else")), If("bool1", "then", "else")),
Bloc("then", Bloc("then",
......
...@@ -32,7 +32,7 @@ type opData struct { ...@@ -32,7 +32,7 @@ type opData struct {
typ string // default result type typ string // default result type
aux string aux string
rematerializeable bool rematerializeable bool
variableLength bool // this operation has a variable number of arguments argLength int32 // number of arguments, if -1, then this operation has a variable number of arguments
commutative bool // this operation is commutative (e.g. addition) commutative bool // this operation is commutative (e.g. addition)
} }
...@@ -126,6 +126,8 @@ func genOp() { ...@@ -126,6 +126,8 @@ func genOp() {
if v.aux != "" { if v.aux != "" {
fmt.Fprintf(w, "auxType: aux%s,\n", v.aux) fmt.Fprintf(w, "auxType: aux%s,\n", v.aux)
} }
fmt.Fprintf(w, "argLen: %d,\n", v.argLength)
if v.rematerializeable { if v.rematerializeable {
if v.reg.clobbers != 0 { if v.reg.clobbers != 0 {
log.Fatalf("%s is rematerializeable and clobbers registers", v.name) log.Fatalf("%s is rematerializeable and clobbers registers", v.name)
...@@ -191,6 +193,7 @@ func genOp() { ...@@ -191,6 +193,7 @@ func genOp() {
var err error var err error
b, err = format.Source(b) b, err = format.Source(b)
if err != nil { if err != nil {
fmt.Printf("%s\n", w.Bytes())
panic(err) panic(err)
} }
......
...@@ -398,14 +398,14 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top ...@@ -398,14 +398,14 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top
variableLength := false variableLength := false
for _, op := range genericOps { for _, op := range genericOps {
if op.name == s[0] { if op.name == s[0] && op.argLength == -1 {
variableLength = op.variableLength variableLength = true
break break
} }
} }
for _, op := range arch.ops { for _, op := range arch.ops {
if op.name == s[0] { if op.name == s[0] && op.argLength == -1 {
variableLength = op.variableLength variableLength = true
break break
} }
} }
......
...@@ -177,7 +177,8 @@ func TestNilcheckAddPtr(t *testing.T) { ...@@ -177,7 +177,8 @@ func TestNilcheckAddPtr(t *testing.T) {
Valu("sb", OpSB, TypeInvalid, 0, nil), Valu("sb", OpSB, TypeInvalid, 0, nil),
Goto("checkPtr")), Goto("checkPtr")),
Bloc("checkPtr", Bloc("checkPtr",
Valu("ptr1", OpAddPtr, ptrType, 0, nil, "sb"), Valu("off", OpConst64, TypeInt64, 20, nil),
Valu("ptr1", OpAddPtr, ptrType, 0, nil, "sb", "off"),
Valu("bool1", OpIsNonNil, TypeBool, 0, nil, "ptr1"), Valu("bool1", OpIsNonNil, TypeBool, 0, nil, "ptr1"),
If("bool1", "extra", "exit")), If("bool1", "extra", "exit")),
Bloc("extra", Bloc("extra",
...@@ -355,7 +356,7 @@ func TestNilcheckUser(t *testing.T) { ...@@ -355,7 +356,7 @@ func TestNilcheckUser(t *testing.T) {
Goto("checkPtr")), Goto("checkPtr")),
Bloc("checkPtr", Bloc("checkPtr",
Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"), Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"), Valu("nilptr", OpConstNil, ptrType, 0, nil),
Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"), Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"),
If("bool1", "secondCheck", "exit")), If("bool1", "secondCheck", "exit")),
Bloc("secondCheck", Bloc("secondCheck",
...@@ -394,7 +395,7 @@ func TestNilcheckBug(t *testing.T) { ...@@ -394,7 +395,7 @@ func TestNilcheckBug(t *testing.T) {
Goto("checkPtr")), Goto("checkPtr")),
Bloc("checkPtr", Bloc("checkPtr",
Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"), Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"), Valu("nilptr", OpConstNil, ptrType, 0, nil),
Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"), Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"),
If("bool1", "secondCheck", "couldBeNil")), If("bool1", "secondCheck", "couldBeNil")),
Bloc("couldBeNil", Bloc("couldBeNil",
......
...@@ -19,6 +19,7 @@ type opInfo struct { ...@@ -19,6 +19,7 @@ type opInfo struct {
asm int asm int
reg regInfo reg regInfo
auxType auxType auxType auxType
argLen int32 // the number of arugments, -1 if variable length
generic bool // this is a generic (arch-independent) opcode generic bool // this is a generic (arch-independent) opcode
rematerializeable bool // this op is rematerializeable rematerializeable bool // this op is rematerializeable
commutative bool // this operation is commutative (e.g. addition) commutative bool // this operation is commutative (e.g. addition)
......
This diff is collapsed.
...@@ -16,10 +16,8 @@ func zcse(f *Func) { ...@@ -16,10 +16,8 @@ func zcse(f *Func) {
for i := 0; i < len(b.Values); { for i := 0; i < len(b.Values); {
v := b.Values[i] v := b.Values[i]
next := true next := true
switch v.Op { if opcodeTable[v.Op].argLen == 0 {
case OpSB, OpConst64, OpConst32, OpConst16, OpConst8, OpConst64F, key := vkey{v.Op, keyFor(v), v.Aux, typeStr(v)}
OpConst32F, OpConstBool, OpConstNil, OpConstSlice, OpConstInterface:
key := vkey{v.Op, keyFor(v), typeStr(v)}
if vals[key] == nil { if vals[key] == nil {
vals[key] = v vals[key] = v
if b != f.Entry { if b != f.Entry {
...@@ -47,11 +45,8 @@ func zcse(f *Func) { ...@@ -47,11 +45,8 @@ func zcse(f *Func) {
for _, b := range f.Blocks { for _, b := range f.Blocks {
for _, v := range b.Values { for _, v := range b.Values {
for i, a := range v.Args { for i, a := range v.Args {
// TODO: encode arglen in the opcode table, then do this switch with a table lookup? if opcodeTable[a.Op].argLen == 0 {
switch a.Op { key := vkey{a.Op, keyFor(a), a.Aux, typeStr(a)}
case OpSB, OpConst64, OpConst32, OpConst16, OpConst8, OpConst64F,
OpConst32F, OpConstBool, OpConstNil, OpConstSlice, OpConstInterface:
key := vkey{a.Op, keyFor(a), typeStr(a)}
if rv, ok := vals[key]; ok { if rv, ok := vals[key]; ok {
v.Args[i] = rv v.Args[i] = rv
} }
...@@ -64,7 +59,8 @@ func zcse(f *Func) { ...@@ -64,7 +59,8 @@ func zcse(f *Func) {
// vkey is a type used to uniquely identify a zero arg value. // vkey is a type used to uniquely identify a zero arg value.
type vkey struct { type vkey struct {
op Op op Op
a int64 // aux ai int64 // aux int
ax interface{} // aux
t string // type t string // type
} }
...@@ -89,7 +85,6 @@ func keyFor(v *Value) int64 { ...@@ -89,7 +85,6 @@ func keyFor(v *Value) int64 {
case OpConst8, OpConstBool: case OpConst8, OpConstBool:
return int64(int8(v.AuxInt)) return int64(int8(v.AuxInt))
default: default:
// Also matches OpSB, OpConstNil, OpConstSlice, OpConstInterface: return v.AuxInt
return 0
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment