and which need code generated, and do the code generation.
Common-Subexpression Elimination
- - Canonicalize types.
- Make better decision about which value in an equivalence class we should
choose to replace other values in that class.
- Can we move control values out of their basic block?
// It starts with a coarse partition and iteratively refines it
// until it reaches a fixed point.
- // Make initial partition based on opcode/type/aux/auxint/nargs
- // TODO(khr): types are not canonical, so we split unnecessarily.
- // For example, all pointer types are distinct. Fix this.
- // As a data point, using v.Type.String() instead of
- // v.Type here (which is unsound) allows removal of
- // about 50% more nil checks in the nilcheck elim pass.
+ // Make initial partition based on opcode/type-name/aux/auxint/nargs
type key struct {
op Op
- typ Type
+ typ string
aux interface{}
auxint int64
nargs int
m := map[key]eqclass{}
for _, b := range f.Blocks {
for _, v := range b.Values {
- k := key{v.Op, v.Type, v.Aux, v.AuxInt, len(v.Args)}
+ k := key{v.Op, v.Type.String(), v.Aux, v.AuxInt, len(v.Args)}
m[k] = append(m[k], v)
}
}
for j := 1; j < len(e); {
w := e[j]
for i := 0; i < len(v.Args); i++ {
- if valueEqClass[v.Args[i].ID] != valueEqClass[w.Args[i].ID] {
+ if valueEqClass[v.Args[i].ID] != valueEqClass[w.Args[i].ID] || !v.Type.Equal(w.Type) {
// w is not equivalent to v.
// remove w from e
e, e[j] = e[:len(e)-1], e[len(e)-1]
PtrTo() Type // given T, return *T
String() string
+ Equal(Type) bool
}
// Stub implementation for now, until we are completely using ../gc:Type
func (t *TypeImpl) Elem() Type { panic("not implemented"); return nil }
func (t *TypeImpl) PtrTo() Type { panic("not implemented"); return nil }
+func (t *TypeImpl) Equal(u Type) bool {
+ x, ok := u.(*TypeImpl)
+ if !ok {
+ return false
+ }
+ return x == t
+}
+
var (
// shortcuts for commonly used basic types
TypeInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Signed: true, Name: "int8"}