]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: load properly constant values from itabs
authorMateusz Poliwczak <mpoliwczak34@gmail.com>
Sun, 16 Feb 2025 17:24:19 +0000 (17:24 +0000)
committerGopher Robot <gobot@golang.org>
Wed, 19 Feb 2025 21:39:00 +0000 (13:39 -0800)
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>
src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
test/codegen/load_type_from_itab.go [new file with mode: 0644]

index 0339370517ca837fd3f6c867cd261a8f84787d5b..8a54645feea30de7c6bf156d64785f9feca6b1d1 100644 (file)
 (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.
-(Load <t> (OffPtr [off]                       (Addr {s} sb)       ) _) && t.IsUintptr() && 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 <t> (OffPtr [off] (ITab (IMake          (Addr {s} sb)    _))) _) && t.IsUintptr() && 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]                       (Addr {s} sb)       ) _)  && 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 <typ.BytePtr> (OffPtr [off] (ITab (IMake          (Addr {s} sb)    _))) _)  && 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.
 (Load <t> (OffPtr [off]                       (Addr {sym} _)       ) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)])
index d0b6e0b1001d04745eed655995798547790b3f81..0cdaded87f15c767d47be7d2c104b6abc62144cd 100644 (file)
@@ -13519,6 +13519,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        config := b.Func.Config
+       typ := &b.Func.Config.Types
        // match: (Load <t1> p1 (Store {t2} p2 x _))
        // cond: isSamePtr(p1, p2) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size()
        // result: x
@@ -14103,12 +14104,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       // match: (Load <t> (OffPtr [off] (Addr {s} sb) ) _)
-       // cond: t.IsUintptr() && isFixedSym(s, off)
+       // match: (Load <typ.BytePtr> (OffPtr [off] (Addr {s} sb) ) _)
+       // cond: isFixedSym(s, off)
        // result: (Addr {fixedSym(b.Func, s, off)} sb)
        for {
-               t := v.Type
-               if v_0.Op != OpOffPtr {
+               if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
                        break
                }
                off := auxIntToInt64(v_0.AuxInt)
@@ -14118,7 +14118,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
                }
                s := auxToSym(v_0_0.Aux)
                sb := v_0_0.Args[0]
-               if !(t.IsUintptr() && isFixedSym(s, off)) {
+               if !(isFixedSym(s, off)) {
                        break
                }
                v.reset(OpAddr)
@@ -14126,12 +14126,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
                v.AddArg(sb)
                return true
        }
-       // match: (Load <t> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
-       // cond: t.IsUintptr() && isFixedSym(s, off)
+       // match: (Load <typ.BytePtr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
+       // cond: isFixedSym(s, off)
        // result: (Addr {fixedSym(b.Func, s, off)} sb)
        for {
-               t := v.Type
-               if v_0.Op != OpOffPtr {
+               if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
                        break
                }
                off := auxIntToInt64(v_0.AuxInt)
@@ -14145,7 +14144,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
                }
                s := auxToSym(v_0_0_0.Aux)
                sb := v_0_0_0.Args[0]
-               if !(t.IsUintptr() && isFixedSym(s, off)) {
+               if !(isFixedSym(s, off)) {
                        break
                }
                v.reset(OpAddr)
@@ -14153,12 +14152,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
                v.AddArg(sb)
                return true
        }
-       // match: (Load <t> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
-       // cond: t.IsUintptr() && isFixedSym(s, off)
+       // match: (Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
+       // cond: isFixedSym(s, off)
        // result: (Addr {fixedSym(b.Func, s, off)} sb)
        for {
-               t := v.Type
-               if v_0.Op != OpOffPtr {
+               if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
                        break
                }
                off := auxIntToInt64(v_0.AuxInt)
@@ -14176,7 +14174,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
                }
                s := auxToSym(v_0_0_0_0.Aux)
                sb := v_0_0_0_0.Args[0]
-               if !(t.IsUintptr() && isFixedSym(s, off)) {
+               if !(isFixedSym(s, off)) {
                        break
                }
                v.reset(OpAddr)
@@ -14184,12 +14182,123 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
                v.AddArg(sb)
                return true
        }
-       // match: (Load <t> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
-       // cond: t.IsUintptr() && isFixedSym(s, off)
+       // match: (Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
+       // cond: isFixedSym(s, off)
        // result: (Addr {fixedSym(b.Func, s, off)} sb)
        for {
-               t := v.Type
-               if v_0.Op != OpOffPtr {
+               if v.Type != typ.BytePtr || 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
+               }
+               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)
@@ -14211,7 +14320,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
                }
                s := auxToSym(v_0_0_0_0_0.Aux)
                sb := v_0_0_0_0_0.Args[0]
-               if !(t.IsUintptr() && isFixedSym(s, off)) {
+               if !(isFixedSym(s, off)) {
                        break
                }
                v.reset(OpAddr)
diff --git a/test/codegen/load_type_from_itab.go b/test/codegen/load_type_from_itab.go
new file mode 100644 (file)
index 0000000..b47044f
--- /dev/null
@@ -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()
+}