mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile/internal/ssa: load constant values from abi.PtrType.Elem
This CL makes the generated code for reflect.TypeFor as simple as an intrinsic function. Fixes #75203 Change-Id: I7bb48787101f07e77ab5c583292e834c28a028d6 Reviewed-on: https://go-review.googlesource.com/c/go/+/700336 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> Auto-Submit: Keith Randall <khr@golang.org>
This commit is contained in:
parent
4373754bc9
commit
df29038486
4 changed files with 371 additions and 0 deletions
|
|
@ -2767,6 +2767,22 @@
|
|||
(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 dictionaries and itabs. For offset 0.
|
||||
(Load <typ.BytePtr> (Addr {s} sb) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
(Load <typ.BytePtr> (Convert (Addr {s} sb) _) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
(Load <typ.BytePtr> (ITab (IMake (Addr {s} sb) _)) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
(Load <typ.BytePtr> (ITab (IMake (Convert (Addr {s} sb) _) _)) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
(Load <typ.Uintptr> (Addr {s} sb) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
(Load <typ.Uintptr> (Convert (Addr {s} sb) _) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
(Load <typ.Uintptr> (ITab (IMake (Addr {s} sb) _)) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
(Load <typ.Uintptr> (ITab (IMake (Convert (Addr {s} sb) _) _)) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
|
||||
// Loading constant values from abi.PtrType.Elem.
|
||||
(Load <t> (OffPtr [off] (Addr {s} sb) ) _) && t.IsPtr() && isPtrElem(s, off) => (Addr {ptrElem(s, off)} sb)
|
||||
(Load <t> (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && t.IsPtr() && isPtrElem(s, off) => (Addr {ptrElem(s, off)} sb)
|
||||
(Load <t> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && t.IsPtr() && isPtrElem(s, off) => (Addr {ptrElem(s, off)} sb)
|
||||
(Load <t> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && t.IsPtr() && isPtrElem(s, off) => (Addr {ptrElem(s, off)} sb)
|
||||
|
||||
// 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] (Convert (Addr {sym} _) _) ) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)])
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/logopt"
|
||||
"cmd/compile/internal/reflectdata"
|
||||
"cmd/compile/internal/rttype"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/s390x"
|
||||
|
|
@ -2012,6 +2013,38 @@ func fixed32(c *Config, sym Sym, off int64) int32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
// isPtrElem returns true if sym is an instance of abi.PtrType and off
|
||||
// is equal to the offset of its Elem field.
|
||||
func isPtrElem(sym Sym, off int64) bool {
|
||||
lsym := sym.(*obj.LSym)
|
||||
if strings.HasPrefix(lsym.Name, "type:*") {
|
||||
if ti, ok := (*lsym.Extra).(*obj.TypeInfo); ok {
|
||||
t := ti.Type.(*types.Type)
|
||||
if t.Kind() == types.TPTR {
|
||||
if off == rttype.PtrType.OffsetOf("Elem") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func ptrElem(sym Sym, off int64) Sym {
|
||||
lsym := sym.(*obj.LSym)
|
||||
if strings.HasPrefix(lsym.Name, "type:*") {
|
||||
if ti, ok := (*lsym.Extra).(*obj.TypeInfo); ok {
|
||||
t := ti.Type.(*types.Type)
|
||||
if t.Kind() == types.TPTR {
|
||||
if off == rttype.PtrType.OffsetOf("Elem") {
|
||||
return reflectdata.TypeLinksym(t.Elem())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
base.Fatalf("ptrElem data not known for %s:%d", sym, off)
|
||||
return nil
|
||||
}
|
||||
|
||||
// isFixedSym returns true if the contents of sym at the given offset
|
||||
// is known and is the constant address of another symbol.
|
||||
func isFixedSym(sym Sym, off int64) bool {
|
||||
|
|
|
|||
|
|
@ -14897,6 +14897,306 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
|||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.BytePtr> (Addr {s} sb) _)
|
||||
// cond: isFixedSym(s, 0)
|
||||
// result: (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
for {
|
||||
if v.Type != typ.BytePtr || v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
s := auxToSym(v_0.Aux)
|
||||
sb := v_0.Args[0]
|
||||
if !(isFixedSym(s, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, 0))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.BytePtr> (Convert (Addr {s} sb) _) _)
|
||||
// cond: isFixedSym(s, 0)
|
||||
// result: (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
for {
|
||||
if v.Type != typ.BytePtr || v_0.Op != OpConvert {
|
||||
break
|
||||
}
|
||||
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, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, 0))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.BytePtr> (ITab (IMake (Addr {s} sb) _)) _)
|
||||
// cond: isFixedSym(s, 0)
|
||||
// result: (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
for {
|
||||
if v.Type != typ.BytePtr || v_0.Op != OpITab {
|
||||
break
|
||||
}
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpIMake {
|
||||
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, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, 0))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.BytePtr> (ITab (IMake (Convert (Addr {s} sb) _) _)) _)
|
||||
// cond: isFixedSym(s, 0)
|
||||
// result: (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
for {
|
||||
if v.Type != typ.BytePtr || v_0.Op != OpITab {
|
||||
break
|
||||
}
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpIMake {
|
||||
break
|
||||
}
|
||||
v_0_0_0 := v_0_0.Args[0]
|
||||
if v_0_0_0.Op != OpConvert {
|
||||
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, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, 0))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.Uintptr> (Addr {s} sb) _)
|
||||
// cond: isFixedSym(s, 0)
|
||||
// result: (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
for {
|
||||
if v.Type != typ.Uintptr || v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
s := auxToSym(v_0.Aux)
|
||||
sb := v_0.Args[0]
|
||||
if !(isFixedSym(s, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, 0))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.Uintptr> (Convert (Addr {s} sb) _) _)
|
||||
// cond: isFixedSym(s, 0)
|
||||
// result: (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
for {
|
||||
if v.Type != typ.Uintptr || v_0.Op != OpConvert {
|
||||
break
|
||||
}
|
||||
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, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, 0))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.Uintptr> (ITab (IMake (Addr {s} sb) _)) _)
|
||||
// cond: isFixedSym(s, 0)
|
||||
// result: (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
for {
|
||||
if v.Type != typ.Uintptr || v_0.Op != OpITab {
|
||||
break
|
||||
}
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpIMake {
|
||||
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, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, 0))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.Uintptr> (ITab (IMake (Convert (Addr {s} sb) _) _)) _)
|
||||
// cond: isFixedSym(s, 0)
|
||||
// result: (Addr {fixedSym(b.Func, s, 0)} sb)
|
||||
for {
|
||||
if v.Type != typ.Uintptr || v_0.Op != OpITab {
|
||||
break
|
||||
}
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpIMake {
|
||||
break
|
||||
}
|
||||
v_0_0_0 := v_0_0.Args[0]
|
||||
if v_0_0_0.Op != OpConvert {
|
||||
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, 0)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, 0))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (Addr {s} sb) ) _)
|
||||
// cond: t.IsPtr() && isPtrElem(s, off)
|
||||
// result: (Addr {ptrElem(s, off)} sb)
|
||||
for {
|
||||
t := v.Type
|
||||
if 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 !(t.IsPtr() && isPtrElem(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(ptrElem(s, off))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
|
||||
// cond: t.IsPtr() && isPtrElem(s, off)
|
||||
// result: (Addr {ptrElem(s, off)} sb)
|
||||
for {
|
||||
t := v.Type
|
||||
if 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 !(t.IsPtr() && isPtrElem(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(ptrElem(s, off))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
|
||||
// cond: t.IsPtr() && isPtrElem(s, off)
|
||||
// result: (Addr {ptrElem(s, off)} sb)
|
||||
for {
|
||||
t := v.Type
|
||||
if 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 !(t.IsPtr() && isPtrElem(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(ptrElem(s, off))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
|
||||
// cond: t.IsPtr() && isPtrElem(s, off)
|
||||
// result: (Addr {ptrElem(s, off)} sb)
|
||||
for {
|
||||
t := v.Type
|
||||
if 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 !(t.IsPtr() && isPtrElem(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(ptrElem(s, off))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (Addr {sym} _) ) _)
|
||||
// cond: t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off)
|
||||
// result: (Const32 [fixed32(config, sym, off)])
|
||||
|
|
|
|||
22
test/codegen/issue75203.go
Normal file
22
test/codegen/issue75203.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// 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.
|
||||
|
||||
package codegen
|
||||
|
||||
import "reflect"
|
||||
|
||||
func f() reflect.Type {
|
||||
// amd64:`LEAQ\stype:\*int\(SB\)`
|
||||
// arm64:`MOVD\s\$type:\*int\(SB\)`
|
||||
return reflect.TypeFor[*int]()
|
||||
}
|
||||
|
||||
func g() reflect.Type {
|
||||
// amd64:`LEAQ\stype:int\(SB\)`
|
||||
// arm64:`MOVD\s\$type:int\(SB\)`
|
||||
return reflect.TypeFor[int]()
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue