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) {
}
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.
canHaveAux := false
......
......@@ -14,7 +14,7 @@ func TestFuseEliminatesOneBranch(t *testing.T) {
Goto("checkPtr")),
Bloc("checkPtr",
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"),
If("bool1", "then", "exit")),
Bloc("then",
......@@ -42,7 +42,7 @@ func TestFuseEliminatesBothBranches(t *testing.T) {
Goto("checkPtr")),
Bloc("checkPtr",
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"),
If("bool1", "then", "else")),
Bloc("then",
......@@ -75,7 +75,7 @@ func TestFuseHandlesPhis(t *testing.T) {
Goto("checkPtr")),
Bloc("checkPtr",
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"),
If("bool1", "then", "else")),
Bloc("then",
......
......@@ -32,8 +32,8 @@ type opData struct {
typ string // default result type
aux string
rematerializeable bool
variableLength bool // this operation has a variable number of arguments
commutative bool // this operation is commutative (e.g. addition)
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)
}
type blockData struct {
......@@ -126,6 +126,8 @@ func genOp() {
if v.aux != "" {
fmt.Fprintf(w, "auxType: aux%s,\n", v.aux)
}
fmt.Fprintf(w, "argLen: %d,\n", v.argLength)
if v.rematerializeable {
if v.reg.clobbers != 0 {
log.Fatalf("%s is rematerializeable and clobbers registers", v.name)
......@@ -191,6 +193,7 @@ func genOp() {
var err error
b, err = format.Source(b)
if err != nil {
fmt.Printf("%s\n", w.Bytes())
panic(err)
}
......
......@@ -398,14 +398,14 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top
variableLength := false
for _, op := range genericOps {
if op.name == s[0] {
variableLength = op.variableLength
if op.name == s[0] && op.argLength == -1 {
variableLength = true
break
}
}
for _, op := range arch.ops {
if op.name == s[0] {
variableLength = op.variableLength
if op.name == s[0] && op.argLength == -1 {
variableLength = true
break
}
}
......
......@@ -177,7 +177,8 @@ func TestNilcheckAddPtr(t *testing.T) {
Valu("sb", OpSB, TypeInvalid, 0, nil),
Goto("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"),
If("bool1", "extra", "exit")),
Bloc("extra",
......@@ -355,7 +356,7 @@ func TestNilcheckUser(t *testing.T) {
Goto("checkPtr")),
Bloc("checkPtr",
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"),
If("bool1", "secondCheck", "exit")),
Bloc("secondCheck",
......@@ -394,7 +395,7 @@ func TestNilcheckBug(t *testing.T) {
Goto("checkPtr")),
Bloc("checkPtr",
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"),
If("bool1", "secondCheck", "couldBeNil")),
Bloc("couldBeNil",
......
......@@ -19,9 +19,10 @@ type opInfo struct {
asm int
reg regInfo
auxType auxType
generic bool // this is a generic (arch-independent) opcode
rematerializeable bool // this op is rematerializeable
commutative bool // this operation is commutative (e.g. addition)
argLen int32 // the number of arugments, -1 if variable length
generic bool // this is a generic (arch-independent) opcode
rematerializeable bool // this op is rematerializeable
commutative bool // this operation is commutative (e.g. addition)
}
type inputInfo struct {
......
This diff is collapsed.
......@@ -16,10 +16,8 @@ func zcse(f *Func) {
for i := 0; i < len(b.Values); {
v := b.Values[i]
next := true
switch v.Op {
case OpSB, OpConst64, OpConst32, OpConst16, OpConst8, OpConst64F,
OpConst32F, OpConstBool, OpConstNil, OpConstSlice, OpConstInterface:
key := vkey{v.Op, keyFor(v), typeStr(v)}
if opcodeTable[v.Op].argLen == 0 {
key := vkey{v.Op, keyFor(v), v.Aux, typeStr(v)}
if vals[key] == nil {
vals[key] = v
if b != f.Entry {
......@@ -47,11 +45,8 @@ func zcse(f *Func) {
for _, b := range f.Blocks {
for _, v := range b.Values {
for i, a := range v.Args {
// TODO: encode arglen in the opcode table, then do this switch with a table lookup?
switch a.Op {
case OpSB, OpConst64, OpConst32, OpConst16, OpConst8, OpConst64F,
OpConst32F, OpConstBool, OpConstNil, OpConstSlice, OpConstInterface:
key := vkey{a.Op, keyFor(a), typeStr(a)}
if opcodeTable[a.Op].argLen == 0 {
key := vkey{a.Op, keyFor(a), a.Aux, typeStr(a)}
if rv, ok := vals[key]; ok {
v.Args[i] = rv
}
......@@ -64,8 +59,9 @@ func zcse(f *Func) {
// vkey is a type used to uniquely identify a zero arg value.
type vkey struct {
op Op
a int64 // aux
t string // type
ai int64 // aux int
ax interface{} // aux
t string // type
}
// typeStr returns a string version of the type of v.
......@@ -89,7 +85,6 @@ func keyFor(v *Value) int64 {
case OpConst8, OpConstBool:
return int64(int8(v.AuxInt))
default:
// Also matches OpSB, OpConstNil, OpConstSlice, OpConstInterface:
return 0
return v.AuxInt
}
}
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