mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
cmd/compile: load properly constant values from itabs
While looking at the SSA of following code, i noticed that these rules do not work properly, and the types are loaded indirectly through an itab, instead of statically. type M interface{ M() } type A interface{ A() } type Impl struct{} func (*Impl) M() {} func (*Impl) A() {} func main() { var a M = &Impl{} a.(A).A() } Change-Id: Ia275993f81a2e7302102d4ff87ac28586023d13c GitHub-Last-Rev: 4bfc9019172929d0b0f1c8a1b7eb28cdbc9b87ef GitHub-Pull-Request: golang/go#71784 Reviewed-on: https://go-review.googlesource.com/c/go/+/649500 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
ba3f568988
commit
43e6525986
@ -2756,10 +2756,14 @@
|
|||||||
(RotateLeft(64|32|16|8) (RotateLeft(64|32|16|8) x c) d) && c.Type.Size() == 1 && d.Type.Size() == 1 => (RotateLeft(64|32|16|8) x (Add8 <c.Type> c d))
|
(RotateLeft(64|32|16|8) (RotateLeft(64|32|16|8) x c) d) && c.Type.Size() == 1 && d.Type.Size() == 1 => (RotateLeft(64|32|16|8) x (Add8 <c.Type> c d))
|
||||||
|
|
||||||
// Loading constant values from dictionaries and itabs.
|
// Loading constant values from dictionaries and itabs.
|
||||||
(Load <t> (OffPtr [off] (Addr {s} sb) ) _) && t.IsUintptr() && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
(Load <typ.BytePtr> (OffPtr [off] (Addr {s} sb) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
(Load <t> (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && t.IsUintptr() && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
(Load <typ.BytePtr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
(Load <t> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && t.IsUintptr() && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
(Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
(Load <t> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && t.IsUintptr() && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
(Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
(Load <typ.Uintptr> (OffPtr [off] (Addr {s} sb) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
(Load <typ.Uintptr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
(Load <typ.Uintptr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
(Load <typ.Uintptr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
|
||||||
// Loading constant values from runtime._type.hash.
|
// Loading constant values from runtime._type.hash.
|
||||||
(Load <t> (OffPtr [off] (Addr {sym} _) ) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)])
|
(Load <t> (OffPtr [off] (Addr {sym} _) ) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)])
|
||||||
|
@ -13519,6 +13519,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
b := v.Block
|
b := v.Block
|
||||||
config := b.Func.Config
|
config := b.Func.Config
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
// match: (Load <t1> p1 (Store {t2} p2 x _))
|
// match: (Load <t1> p1 (Store {t2} p2 x _))
|
||||||
// cond: isSamePtr(p1, p2) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size()
|
// cond: isSamePtr(p1, p2) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size()
|
||||||
// result: x
|
// result: x
|
||||||
@ -14103,12 +14104,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Load <t> (OffPtr [off] (Addr {s} sb) ) _)
|
// match: (Load <typ.BytePtr> (OffPtr [off] (Addr {s} sb) ) _)
|
||||||
// cond: t.IsUintptr() && isFixedSym(s, off)
|
// cond: isFixedSym(s, off)
|
||||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
for {
|
for {
|
||||||
t := v.Type
|
if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
|
||||||
if v_0.Op != OpOffPtr {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
off := auxIntToInt64(v_0.AuxInt)
|
off := auxIntToInt64(v_0.AuxInt)
|
||||||
@ -14118,7 +14118,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
}
|
}
|
||||||
s := auxToSym(v_0_0.Aux)
|
s := auxToSym(v_0_0.Aux)
|
||||||
sb := v_0_0.Args[0]
|
sb := v_0_0.Args[0]
|
||||||
if !(t.IsUintptr() && isFixedSym(s, off)) {
|
if !(isFixedSym(s, off)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAddr)
|
v.reset(OpAddr)
|
||||||
@ -14126,12 +14126,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
v.AddArg(sb)
|
v.AddArg(sb)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Load <t> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
|
// match: (Load <typ.BytePtr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
|
||||||
// cond: t.IsUintptr() && isFixedSym(s, off)
|
// cond: isFixedSym(s, off)
|
||||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
for {
|
for {
|
||||||
t := v.Type
|
if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
|
||||||
if v_0.Op != OpOffPtr {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
off := auxIntToInt64(v_0.AuxInt)
|
off := auxIntToInt64(v_0.AuxInt)
|
||||||
@ -14145,7 +14144,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
}
|
}
|
||||||
s := auxToSym(v_0_0_0.Aux)
|
s := auxToSym(v_0_0_0.Aux)
|
||||||
sb := v_0_0_0.Args[0]
|
sb := v_0_0_0.Args[0]
|
||||||
if !(t.IsUintptr() && isFixedSym(s, off)) {
|
if !(isFixedSym(s, off)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAddr)
|
v.reset(OpAddr)
|
||||||
@ -14153,12 +14152,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
v.AddArg(sb)
|
v.AddArg(sb)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Load <t> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
|
// match: (Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
|
||||||
// cond: t.IsUintptr() && isFixedSym(s, off)
|
// cond: isFixedSym(s, off)
|
||||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
for {
|
for {
|
||||||
t := v.Type
|
if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
|
||||||
if v_0.Op != OpOffPtr {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
off := auxIntToInt64(v_0.AuxInt)
|
off := auxIntToInt64(v_0.AuxInt)
|
||||||
@ -14176,7 +14174,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
}
|
}
|
||||||
s := auxToSym(v_0_0_0_0.Aux)
|
s := auxToSym(v_0_0_0_0.Aux)
|
||||||
sb := v_0_0_0_0.Args[0]
|
sb := v_0_0_0_0.Args[0]
|
||||||
if !(t.IsUintptr() && isFixedSym(s, off)) {
|
if !(isFixedSym(s, off)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAddr)
|
v.reset(OpAddr)
|
||||||
@ -14184,12 +14182,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
v.AddArg(sb)
|
v.AddArg(sb)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Load <t> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
|
// match: (Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
|
||||||
// cond: t.IsUintptr() && isFixedSym(s, off)
|
// cond: isFixedSym(s, off)
|
||||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
for {
|
for {
|
||||||
t := v.Type
|
if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
|
||||||
if v_0.Op != OpOffPtr {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
off := auxIntToInt64(v_0.AuxInt)
|
off := auxIntToInt64(v_0.AuxInt)
|
||||||
@ -14211,7 +14208,119 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||||||
}
|
}
|
||||||
s := auxToSym(v_0_0_0_0_0.Aux)
|
s := auxToSym(v_0_0_0_0_0.Aux)
|
||||||
sb := v_0_0_0_0_0.Args[0]
|
sb := v_0_0_0_0_0.Args[0]
|
||||||
if !(t.IsUintptr() && isFixedSym(s, off)) {
|
if !(isFixedSym(s, off)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpAddr)
|
||||||
|
v.Aux = symToAux(fixedSym(b.Func, s, off))
|
||||||
|
v.AddArg(sb)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Load <typ.Uintptr> (OffPtr [off] (Addr {s} sb) ) _)
|
||||||
|
// cond: isFixedSym(s, off)
|
||||||
|
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
for {
|
||||||
|
if v.Type != typ.Uintptr || v_0.Op != OpOffPtr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off := auxIntToInt64(v_0.AuxInt)
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
if v_0_0.Op != OpAddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s := auxToSym(v_0_0.Aux)
|
||||||
|
sb := v_0_0.Args[0]
|
||||||
|
if !(isFixedSym(s, off)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpAddr)
|
||||||
|
v.Aux = symToAux(fixedSym(b.Func, s, off))
|
||||||
|
v.AddArg(sb)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Load <typ.Uintptr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
|
||||||
|
// cond: isFixedSym(s, off)
|
||||||
|
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
for {
|
||||||
|
if v.Type != typ.Uintptr || v_0.Op != OpOffPtr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off := auxIntToInt64(v_0.AuxInt)
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
if v_0_0.Op != OpConvert {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0_0 := v_0_0.Args[0]
|
||||||
|
if v_0_0_0.Op != OpAddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s := auxToSym(v_0_0_0.Aux)
|
||||||
|
sb := v_0_0_0.Args[0]
|
||||||
|
if !(isFixedSym(s, off)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpAddr)
|
||||||
|
v.Aux = symToAux(fixedSym(b.Func, s, off))
|
||||||
|
v.AddArg(sb)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Load <typ.Uintptr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
|
||||||
|
// cond: isFixedSym(s, off)
|
||||||
|
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
for {
|
||||||
|
if v.Type != typ.Uintptr || v_0.Op != OpOffPtr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off := auxIntToInt64(v_0.AuxInt)
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
if v_0_0.Op != OpITab {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0_0 := v_0_0.Args[0]
|
||||||
|
if v_0_0_0.Op != OpIMake {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0_0_0 := v_0_0_0.Args[0]
|
||||||
|
if v_0_0_0_0.Op != OpAddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s := auxToSym(v_0_0_0_0.Aux)
|
||||||
|
sb := v_0_0_0_0.Args[0]
|
||||||
|
if !(isFixedSym(s, off)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpAddr)
|
||||||
|
v.Aux = symToAux(fixedSym(b.Func, s, off))
|
||||||
|
v.AddArg(sb)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Load <typ.Uintptr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
|
||||||
|
// cond: isFixedSym(s, off)
|
||||||
|
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||||
|
for {
|
||||||
|
if v.Type != typ.Uintptr || v_0.Op != OpOffPtr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off := auxIntToInt64(v_0.AuxInt)
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
if v_0_0.Op != OpITab {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0_0 := v_0_0.Args[0]
|
||||||
|
if v_0_0_0.Op != OpIMake {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0_0_0 := v_0_0_0.Args[0]
|
||||||
|
if v_0_0_0_0.Op != OpConvert {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0_0_0_0 := v_0_0_0_0.Args[0]
|
||||||
|
if v_0_0_0_0_0.Op != OpAddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s := auxToSym(v_0_0_0_0_0.Aux)
|
||||||
|
sb := v_0_0_0_0_0.Args[0]
|
||||||
|
if !(isFixedSym(s, off)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAddr)
|
v.reset(OpAddr)
|
||||||
|
24
test/codegen/load_type_from_itab.go
Normal file
24
test/codegen/load_type_from_itab.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// asmcheck
|
||||||
|
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This test makes sure that we statically load a type from an itab, instead
|
||||||
|
// of doing a indirect load from thet itab.
|
||||||
|
|
||||||
|
package codegen
|
||||||
|
|
||||||
|
type M interface{ M() }
|
||||||
|
type A interface{ A() }
|
||||||
|
|
||||||
|
type Impl struct{}
|
||||||
|
|
||||||
|
func (*Impl) M() {}
|
||||||
|
func (*Impl) A() {}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var a M = &Impl{}
|
||||||
|
// amd64:`LEAQ\ttype:.*Impl`
|
||||||
|
a.(A).A()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user