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/21483
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
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
// end, returning an ssa.Cmp (one of CMPlt, CMPeq, CMPgt).
// The answers are correct for an optimizer
-// or code generator, but not for Go source.
-// For example, "type gcDrainFlags int" results in
-// two Go-different types that Compare equal.
-// The order chosen is also arbitrary, only division into
-// equivalence classes (Types that compare CMPeq) matters.
+// or code generator, but not necessarily typechecking.
+// The order chosen is arbitrary, only consistency and division
+// into equivalence classes (Types that compare CMPeq) matters.
func (t *Type) Compare(u ssa.Type) ssa.Cmp {
x, ok := u.(*Type)
// ssa.CompilerType is smaller than gc.Type
------------
- Start another architecture (arm?)
- 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 introduce a new type equality routine that is less strict than the frontend's?
- Infrastructure for enabling/disabling/configuring passes
- Modify logging for at least pass=1, to be Warnl compatible
break
}
}
- if !equivalent || !v.Type.Equal(w.Type) {
+ if !equivalent || v.Type.Compare(w.Type) != CMPeq {
// w is not equivalent to v.
// move it to the end and shrink e.
e[j], e[len(e)-1] = e[len(e)-1], e[j]
}
vv := f.constants[c]
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 {
panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c))
}
} else {
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] {
h := f.getHome(id)
if h != nil && h.(LocalSlot).N == name.N && h.(LocalSlot).Off == name.Off {
if s.values[v.ID].needSlot {
live.remove(v.ID)
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[id] = append(s.interfere[id], v.ID)
}
String() string
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.
}
// Special compiler-only types.
return CMPlt
}
-func (t *CompilerType) Equal(u Type) bool {
- x, ok := u.(*CompilerType)
- if !ok {
- return false
- }
- return x == t
-}
-
var (
TypeInvalid = &CompilerType{Name: "invalid"}
TypeMem = &CompilerType{Name: "mem", Memory: true}