aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
authorYoulin Feng <fengyoulin@live.com>2025-09-01 18:31:29 +0800
committerGopher Robot <gobot@golang.org>2025-09-04 07:25:26 -0700
commitdf290384864c0b3cbb557ef11fc95a29d52f6aca (patch)
treee9d188db9c4620d674f8b443934568b68a1c6465 /src/cmd/compile
parent4373754bc990fc13b27ae823f977bc6328cc331e (diff)
downloadgo-df290384864c0b3cbb557ef11fc95a29d52f6aca.tar.xz
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>
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/ssa/_gen/generic.rules16
-rw-r--r--src/cmd/compile/internal/ssa/rewrite.go33
-rw-r--r--src/cmd/compile/internal/ssa/rewritegeneric.go300
3 files changed, 349 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules
index da112abbf5..c5e2507a14 100644
--- a/src/cmd/compile/internal/ssa/_gen/generic.rules
+++ b/src/cmd/compile/internal/ssa/_gen/generic.rules
@@ -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)])
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
index 6704c7d6e0..8f331c283a 100644
--- a/src/cmd/compile/internal/ssa/rewrite.go
+++ b/src/cmd/compile/internal/ssa/rewrite.go
@@ -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 {
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
index 5394747ba5..a0a4960397 100644
--- a/src/cmd/compile/internal/ssa/rewritegeneric.go
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -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)])