]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/ssa: load constant values from abi.PtrType.Elem
authorYoulin Feng <fengyoulin@live.com>
Mon, 1 Sep 2025 10:31:29 +0000 (18:31 +0800)
committerGopher Robot <gobot@golang.org>
Thu, 4 Sep 2025 14:25:26 +0000 (07:25 -0700)
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>

src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewritegeneric.go
test/codegen/issue75203.go [new file with mode: 0644]

index da112abbf5677ede19ddceff457920f677bdd21d..c5e2507a14fd682fcf5a505e29e5fe4d0d715b4f 100644 (file)
 (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)])
index 6704c7d6e0294a1bce275ef781a9e9157f580cab..8f331c283a66e0cab1d24d2329c494685b9eace9 100644 (file)
@@ -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 {
index 5394747ba577175f97748b54f5e06b804935818c..a0a4960397d809cb39ea958f9f988aa7eb8b2507 100644 (file)
@@ -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)])
diff --git a/test/codegen/issue75203.go b/test/codegen/issue75203.go
new file mode 100644 (file)
index 0000000..68e1794
--- /dev/null
@@ -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]()
+}
+