mirror of
https://github.com/golang/go
synced 2024-11-24 22:27:57 -07:00
[dev.ssa] cmd/compile/internal/ssa: handle commutative operations in cse
* If a operation is commutative order the parameters in a canonical way. Size of pkg/tool/linux_amd64/* excluding compile: before: 95882288 after: 95868152 change: 14136 ~0.015% I tried something similar with Leq and Geq, but the results were not great because it confuses the 'lowered cse' pass too much which can no longer remove redundant comparisons from IsInBounds. Change-Id: I2f928663a11320bfc51c7fa47e384b7411c420ba Reviewed-on: https://go-review.googlesource.com/19727 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
b86cafc7dc
commit
88c1ef5b45
@ -35,6 +35,10 @@ func cse(f *Func) {
|
|||||||
if v.Type.IsMemory() {
|
if v.Type.IsMemory() {
|
||||||
continue // memory values can never cse
|
continue // memory values can never cse
|
||||||
}
|
}
|
||||||
|
if opcodeTable[v.Op].commutative && len(v.Args) == 2 && v.Args[1].ID < v.Args[0].ID {
|
||||||
|
// Order the arguments of binary commutative operations.
|
||||||
|
v.Args[0], v.Args[1] = v.Args[1], v.Args[0]
|
||||||
|
}
|
||||||
a = append(a, v)
|
a = append(a, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ var genericOps = []opData{
|
|||||||
// 2-input arithmetic
|
// 2-input arithmetic
|
||||||
// Types must be consistent with Go typing. Add, for example, must take two values
|
// Types must be consistent with Go typing. Add, for example, must take two values
|
||||||
// of the same type and produces that same type.
|
// of the same type and produces that same type.
|
||||||
{name: "Add8"}, // arg0 + arg1
|
{name: "Add8", commutative: true}, // arg0 + arg1
|
||||||
{name: "Add16"},
|
{name: "Add16", commutative: true},
|
||||||
{name: "Add32"},
|
{name: "Add32", commutative: true},
|
||||||
{name: "Add64"},
|
{name: "Add64", commutative: true},
|
||||||
{name: "AddPtr"}, // For address calculations. arg0 is a pointer and arg1 is an int.
|
{name: "AddPtr"}, // For address calculations. arg0 is a pointer and arg1 is an int.
|
||||||
{name: "Add32F"},
|
{name: "Add32F"},
|
||||||
{name: "Add64F"},
|
{name: "Add64F"},
|
||||||
@ -25,10 +25,10 @@ var genericOps = []opData{
|
|||||||
{name: "Sub32F"},
|
{name: "Sub32F"},
|
||||||
{name: "Sub64F"},
|
{name: "Sub64F"},
|
||||||
|
|
||||||
{name: "Mul8"}, // arg0 * arg1
|
{name: "Mul8", commutative: true}, // arg0 * arg1
|
||||||
{name: "Mul16"},
|
{name: "Mul16", commutative: true},
|
||||||
{name: "Mul32"},
|
{name: "Mul32", commutative: true},
|
||||||
{name: "Mul64"},
|
{name: "Mul64", commutative: true},
|
||||||
{name: "Mul32F"},
|
{name: "Mul32F"},
|
||||||
{name: "Mul64F"},
|
{name: "Mul64F"},
|
||||||
|
|
||||||
@ -65,20 +65,20 @@ var genericOps = []opData{
|
|||||||
{name: "Mod64"},
|
{name: "Mod64"},
|
||||||
{name: "Mod64u"},
|
{name: "Mod64u"},
|
||||||
|
|
||||||
{name: "And8"}, // arg0 & arg1
|
{name: "And8", commutative: true}, // arg0 & arg1
|
||||||
{name: "And16"},
|
{name: "And16", commutative: true},
|
||||||
{name: "And32"},
|
{name: "And32", commutative: true},
|
||||||
{name: "And64"},
|
{name: "And64", commutative: true},
|
||||||
|
|
||||||
{name: "Or8"}, // arg0 | arg1
|
{name: "Or8", commutative: true}, // arg0 | arg1
|
||||||
{name: "Or16"},
|
{name: "Or16", commutative: true},
|
||||||
{name: "Or32"},
|
{name: "Or32", commutative: true},
|
||||||
{name: "Or64"},
|
{name: "Or64", commutative: true},
|
||||||
|
|
||||||
{name: "Xor8"}, // arg0 ^ arg1
|
{name: "Xor8", commutative: true}, // arg0 ^ arg1
|
||||||
{name: "Xor16"},
|
{name: "Xor16", commutative: true},
|
||||||
{name: "Xor32"},
|
{name: "Xor32", commutative: true},
|
||||||
{name: "Xor64"},
|
{name: "Xor64", commutative: true},
|
||||||
|
|
||||||
// For shifts, AxB means the shifted value has A bits and the shift amount has B bits.
|
// For shifts, AxB means the shifted value has A bits and the shift amount has B bits.
|
||||||
{name: "Lsh8x8"}, // arg0 << arg1
|
{name: "Lsh8x8"}, // arg0 << arg1
|
||||||
@ -158,21 +158,21 @@ var genericOps = []opData{
|
|||||||
{name: "Lrot64", aux: "Int64"},
|
{name: "Lrot64", aux: "Int64"},
|
||||||
|
|
||||||
// 2-input comparisons
|
// 2-input comparisons
|
||||||
{name: "Eq8"}, // arg0 == arg1
|
{name: "Eq8", commutative: true}, // arg0 == arg1
|
||||||
{name: "Eq16"},
|
{name: "Eq16", commutative: true},
|
||||||
{name: "Eq32"},
|
{name: "Eq32", commutative: true},
|
||||||
{name: "Eq64"},
|
{name: "Eq64", commutative: true},
|
||||||
{name: "EqPtr"},
|
{name: "EqPtr", commutative: true},
|
||||||
{name: "EqInter"}, // arg0 or arg1 is nil; other cases handled by frontend
|
{name: "EqInter"}, // arg0 or arg1 is nil; other cases handled by frontend
|
||||||
{name: "EqSlice"}, // arg0 or arg1 is nil; other cases handled by frontend
|
{name: "EqSlice"}, // arg0 or arg1 is nil; other cases handled by frontend
|
||||||
{name: "Eq32F"},
|
{name: "Eq32F"},
|
||||||
{name: "Eq64F"},
|
{name: "Eq64F"},
|
||||||
|
|
||||||
{name: "Neq8"}, // arg0 != arg1
|
{name: "Neq8", commutative: true}, // arg0 != arg1
|
||||||
{name: "Neq16"},
|
{name: "Neq16", commutative: true},
|
||||||
{name: "Neq32"},
|
{name: "Neq32", commutative: true},
|
||||||
{name: "Neq64"},
|
{name: "Neq64", commutative: true},
|
||||||
{name: "NeqPtr"},
|
{name: "NeqPtr", commutative: true},
|
||||||
{name: "NeqInter"}, // arg0 or arg1 is nil; other cases handled by frontend
|
{name: "NeqInter"}, // arg0 or arg1 is nil; other cases handled by frontend
|
||||||
{name: "NeqSlice"}, // arg0 or arg1 is nil; other cases handled by frontend
|
{name: "NeqSlice"}, // arg0 or arg1 is nil; other cases handled by frontend
|
||||||
{name: "Neq32F"},
|
{name: "Neq32F"},
|
||||||
|
@ -32,7 +32,8 @@ type opData struct {
|
|||||||
typ string // default result type
|
typ string // default result type
|
||||||
aux string
|
aux string
|
||||||
rematerializeable bool
|
rematerializeable bool
|
||||||
variableLength bool // if true the operation has a variable number of arguments
|
variableLength bool // this operation has a variable number of arguments
|
||||||
|
commutative bool // this operation is commutative (e.g. addition)
|
||||||
}
|
}
|
||||||
|
|
||||||
type blockData struct {
|
type blockData struct {
|
||||||
@ -131,6 +132,9 @@ func genOp() {
|
|||||||
}
|
}
|
||||||
fmt.Fprintln(w, "rematerializeable: true,")
|
fmt.Fprintln(w, "rematerializeable: true,")
|
||||||
}
|
}
|
||||||
|
if v.commutative {
|
||||||
|
fmt.Fprintln(w, "commutative: true,")
|
||||||
|
}
|
||||||
if a.name == "generic" {
|
if a.name == "generic" {
|
||||||
fmt.Fprintln(w, "generic:true,")
|
fmt.Fprintln(w, "generic:true,")
|
||||||
fmt.Fprintln(w, "},") // close op
|
fmt.Fprintln(w, "},") // close op
|
||||||
|
@ -21,6 +21,7 @@ type opInfo struct {
|
|||||||
auxType auxType
|
auxType auxType
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
type inputInfo struct {
|
type inputInfo struct {
|
||||||
|
@ -3598,18 +3598,22 @@ var opcodeTable = [...]opInfo{
|
|||||||
|
|
||||||
{
|
{
|
||||||
name: "Add8",
|
name: "Add8",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Add16",
|
name: "Add16",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Add32",
|
name: "Add32",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Add64",
|
name: "Add64",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3654,18 +3658,22 @@ var opcodeTable = [...]opInfo{
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Mul8",
|
name: "Mul8",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Mul16",
|
name: "Mul16",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Mul32",
|
name: "Mul32",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Mul64",
|
name: "Mul64",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3786,50 +3794,62 @@ var opcodeTable = [...]opInfo{
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "And8",
|
name: "And8",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "And16",
|
name: "And16",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "And32",
|
name: "And32",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "And64",
|
name: "And64",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Or8",
|
name: "Or8",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Or16",
|
name: "Or16",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Or32",
|
name: "Or32",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Or64",
|
name: "Or64",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Xor8",
|
name: "Xor8",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Xor16",
|
name: "Xor16",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Xor32",
|
name: "Xor32",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Xor64",
|
name: "Xor64",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4046,22 +4066,27 @@ var opcodeTable = [...]opInfo{
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Eq8",
|
name: "Eq8",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Eq16",
|
name: "Eq16",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Eq32",
|
name: "Eq32",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Eq64",
|
name: "Eq64",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "EqPtr",
|
name: "EqPtr",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4082,22 +4107,27 @@ var opcodeTable = [...]opInfo{
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Neq8",
|
name: "Neq8",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Neq16",
|
name: "Neq16",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Neq32",
|
name: "Neq32",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Neq64",
|
name: "Neq64",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "NeqPtr",
|
name: "NeqPtr",
|
||||||
|
commutative: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user