Commit 2563b6f9 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile/internal/ssa: use Compare instead of Equal

They have different semantics.

Equal is stricter and is designed for the front-end.
Compare is looser and cheaper and is designed for the back-end.
To avoid possible regression, remove Equal from ssa.Type.

Updates #15043

Change-Id: Ie23ce75ff6b4d01b7982e0a89e6f81b5d099d8d6
Reviewed-on: https://go-review.googlesource.com/21483Reviewed-by: default avatarDavid Chase <drchase@google.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
parent 462aa7ec
...@@ -863,19 +863,12 @@ func (t *Type) SimpleString() string { ...@@ -863,19 +863,12 @@ func (t *Type) SimpleString() string {
return Econv(t.Etype) return Econv(t.Etype)
} }
func (t *Type) Equal(u ssa.Type) bool {
x, ok := u.(*Type)
return ok && Eqtype(t, x)
}
// Compare compares types for purposes of the SSA back // Compare compares types for purposes of the SSA back
// end, returning an ssa.Cmp (one of CMPlt, CMPeq, CMPgt). // end, returning an ssa.Cmp (one of CMPlt, CMPeq, CMPgt).
// The answers are correct for an optimizer // The answers are correct for an optimizer
// or code generator, but not for Go source. // or code generator, but not necessarily typechecking.
// For example, "type gcDrainFlags int" results in // The order chosen is arbitrary, only consistency and division
// two Go-different types that Compare equal. // into equivalence classes (Types that compare CMPeq) matters.
// The order chosen is also arbitrary, only division into
// equivalence classes (Types that compare CMPeq) matters.
func (t *Type) Compare(u ssa.Type) ssa.Cmp { func (t *Type) Compare(u ssa.Type) ssa.Cmp {
x, ok := u.(*Type) x, ok := u.(*Type)
// ssa.CompilerType is smaller than gc.Type // ssa.CompilerType is smaller than gc.Type
......
...@@ -41,8 +41,6 @@ Future/other ...@@ -41,8 +41,6 @@ Future/other
------------ ------------
- Start another architecture (arm?) - Start another architecture (arm?)
- 64-bit ops on 32-bit machines - 64-bit ops on 32-bit machines
- Investigate type equality. During SSA generation, should we use n.Type or (say) TypeBool?
- Should we get rid of named types in favor of underlying types during SSA generation? - Should we get rid of named types in favor of underlying types during SSA generation?
- Should we introduce a new type equality routine that is less strict than the frontend's?
- Infrastructure for enabling/disabling/configuring passes - Infrastructure for enabling/disabling/configuring passes
- Modify logging for at least pass=1, to be Warnl compatible - Modify logging for at least pass=1, to be Warnl compatible
...@@ -108,7 +108,7 @@ func cse(f *Func) { ...@@ -108,7 +108,7 @@ func cse(f *Func) {
break break
} }
} }
if !equivalent || !v.Type.Equal(w.Type) { if !equivalent || v.Type.Compare(w.Type) != CMPeq {
// w is not equivalent to v. // w is not equivalent to v.
// move it to the end and shrink e. // move it to the end and shrink e.
e[j], e[len(e)-1] = e[len(e)-1], e[j] e[j], e[len(e)-1] = e[len(e)-1], e[j]
......
...@@ -318,7 +318,7 @@ func (f *Func) constVal(line int32, op Op, t Type, c int64, setAux bool) *Value ...@@ -318,7 +318,7 @@ func (f *Func) constVal(line int32, op Op, t Type, c int64, setAux bool) *Value
} }
vv := f.constants[c] vv := f.constants[c]
for _, v := range vv { for _, v := range vv {
if v.Op == op && v.Type.Equal(t) { if v.Op == op && v.Type.Compare(t) == CMPeq {
if setAux && v.AuxInt != c { if setAux && v.AuxInt != c {
panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c)) panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c))
} }
......
...@@ -201,7 +201,7 @@ func (s *stackAllocState) stackalloc() { ...@@ -201,7 +201,7 @@ func (s *stackAllocState) stackalloc() {
} else { } else {
name = names[v.ID] name = names[v.ID]
} }
if name.N != nil && v.Type.Equal(name.Type) { if name.N != nil && v.Type.Compare(name.Type) == CMPeq {
for _, id := range s.interfere[v.ID] { for _, id := range s.interfere[v.ID] {
h := f.getHome(id) h := f.getHome(id)
if h != nil && h.(LocalSlot).N == name.N && h.(LocalSlot).Off == name.Off { if h != nil && h.(LocalSlot).N == name.N && h.(LocalSlot).Off == name.Off {
...@@ -372,7 +372,7 @@ func (s *stackAllocState) buildInterferenceGraph() { ...@@ -372,7 +372,7 @@ func (s *stackAllocState) buildInterferenceGraph() {
if s.values[v.ID].needSlot { if s.values[v.ID].needSlot {
live.remove(v.ID) live.remove(v.ID)
for _, id := range live.contents() { for _, id := range live.contents() {
if s.values[v.ID].typ.Equal(s.values[id].typ) { if s.values[v.ID].typ.Compare(s.values[id].typ) == CMPeq {
s.interfere[v.ID] = append(s.interfere[v.ID], id) s.interfere[v.ID] = append(s.interfere[v.ID], id)
s.interfere[id] = append(s.interfere[id], v.ID) s.interfere[id] = append(s.interfere[id], v.ID)
} }
......
...@@ -40,7 +40,6 @@ type Type interface { ...@@ -40,7 +40,6 @@ type Type interface {
String() string String() string
SimpleString() string // a coarser generic description of T, e.g. T's underlying type SimpleString() string // a coarser generic description of T, e.g. T's underlying type
Equal(Type) bool
Compare(Type) Cmp // compare types, returning one of CMPlt, CMPeq, CMPgt. Compare(Type) Cmp // compare types, returning one of CMPlt, CMPeq, CMPgt.
} }
...@@ -117,14 +116,6 @@ func (t *CompilerType) Compare(u Type) Cmp { ...@@ -117,14 +116,6 @@ func (t *CompilerType) Compare(u Type) Cmp {
return CMPlt return CMPlt
} }
func (t *CompilerType) Equal(u Type) bool {
x, ok := u.(*CompilerType)
if !ok {
return false
}
return x == t
}
var ( var (
TypeInvalid = &CompilerType{Name: "invalid"} TypeInvalid = &CompilerType{Name: "invalid"}
TypeMem = &CompilerType{Name: "mem", Memory: true} TypeMem = &CompilerType{Name: "mem", Memory: true}
......
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