From: Jake Bailey Date: Fri, 5 Sep 2025 20:08:21 +0000 (-0700) Subject: cmd/compile: consolidate logic for rewriting fixed loads X-Git-Tag: go1.26rc1~941 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b915e14490e1c3ac5a84c274bfab647e1cb105a7;p=gostls13.git cmd/compile: consolidate logic for rewriting fixed loads Many CLs have worked with this bit of code, extending the cases more and more for various fixed addresses and constants. But, I find that it's getting duplicitive, and I don't find the current setup very clear that something like isFixed32 _only_ works for a specific element within the type data. This CL rewrites these rules (pun unintended) into a single set of rewrite rules with shared logic, which stops hardcoding offsets and type compatibility checks. This should open the door to optimizing further type:... field loads, of which most can be done entirely statically but are not yet today outside Hash and Elem. Passes toolstash -cmp. Change-Id: I754138ce1785c6036eada9ed53f0ce2ad2a58b63 Reviewed-on: https://go-review.googlesource.com/c/go/+/701297 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Auto-Submit: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-by: Mark Freeman Reviewed-by: Florian Lehner --- diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 6255045c6f..c0806c2243 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -2757,37 +2757,15 @@ (RotateLeft(64|32|16|8) (RotateLeft(64|32|16|8) x c) d) && c.Type.Size() == 2 && d.Type.Size() == 2 => (RotateLeft(64|32|16|8) x (Add16 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 d)) -// Loading constant values from dictionaries and itabs. -(Load (OffPtr [off] (Addr {s} sb) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb) -(Load (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb) -(Load (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb) -(Load (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb) -(Load (OffPtr [off] (Addr {s} sb) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb) -(Load (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb) -(Load (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb) -(Load (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 (Addr {s} sb) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb) -(Load (Convert (Addr {s} sb) _) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb) -(Load (ITab (IMake (Addr {s} sb) _)) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb) -(Load (ITab (IMake (Convert (Addr {s} sb) _) _)) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb) -(Load (Addr {s} sb) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb) -(Load (Convert (Addr {s} sb) _) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb) -(Load (ITab (IMake (Addr {s} sb) _)) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb) -(Load (ITab (IMake (Convert (Addr {s} sb) _) _)) _) && isFixedSym(s, 0) => (Addr {fixedSym(b.Func, s, 0)} sb) - -// Loading constant values from abi.PtrType.Elem. -(Load (OffPtr [off] (Addr {s} sb) ) _) && t.IsPtr() && isPtrElem(s, off) => (Addr {ptrElem(b.Func, s, off)} sb) -(Load (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && t.IsPtr() && isPtrElem(s, off) => (Addr {ptrElem(b.Func, s, off)} sb) -(Load (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && t.IsPtr() && isPtrElem(s, off) => (Addr {ptrElem(b.Func, s, off)} sb) -(Load (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && t.IsPtr() && isPtrElem(s, off) => (Addr {ptrElem(b.Func, s, off)} sb) - -// Loading constant values from runtime._type.hash. -(Load (OffPtr [off] (Addr {sym} _) ) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)]) -(Load (OffPtr [off] (Convert (Addr {sym} _) _) ) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)]) -(Load (OffPtr [off] (ITab (IMake (Addr {sym} _) _))) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)]) -(Load (OffPtr [off] (ITab (IMake (Convert (Addr {sym} _) _) _))) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)]) +// Loading fixed addresses and constants. +(Load (Addr {s} sb) _) && isFixedLoad(v, s, 0) => rewriteFixedLoad(v, s, sb, 0) +(Load (Convert (Addr {s} sb) _) _) && isFixedLoad(v, s, 0) => rewriteFixedLoad(v, s, sb, 0) +(Load (ITab (IMake (Addr {s} sb) _)) _) && isFixedLoad(v, s, 0) => rewriteFixedLoad(v, s, sb, 0) +(Load (ITab (IMake (Convert (Addr {s} sb) _) _)) _) && isFixedLoad(v, s, 0) => rewriteFixedLoad(v, s, sb, 0) +(Load (OffPtr [off] (Addr {s} sb) ) _) && isFixedLoad(v, s, off) => rewriteFixedLoad(v, s, sb, off) +(Load (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && isFixedLoad(v, s, off) => rewriteFixedLoad(v, s, sb, off) +(Load (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && isFixedLoad(v, s, off) => rewriteFixedLoad(v, s, sb, off) +(Load (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && isFixedLoad(v, s, off) => rewriteFixedLoad(v, s, sb, off) // Calling cmpstring a second time with the same arguments in the // same memory state can reuse the results of the first call. diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index a4242c2141..bc66c91a35 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1982,108 +1982,111 @@ func symIsROZero(sym Sym) bool { return true } -// isFixed32 returns true if the int32 at offset off in symbol sym -// is known and constant. -func isFixed32(c *Config, sym Sym, off int64) bool { - return isFixed(c, sym, off, 4) -} - -// isFixed returns true if the range [off,off+size] of the symbol sym -// is known and constant. -func isFixed(c *Config, sym Sym, off, size int64) bool { - lsym := sym.(*obj.LSym) - if lsym.Extra == nil { - return false - } - if _, ok := (*lsym.Extra).(*obj.TypeInfo); ok { - if off == 2*c.PtrSize && size == 4 { - return true // type hash field - } - } - return false -} -func fixed32(c *Config, sym Sym, off int64) int32 { +// isFixedLoad returns true if the load can be resolved to fixed address or constant, +// and can be rewritten by rewriteFixedLoad. +func isFixedLoad(v *Value, sym Sym, off int64) bool { lsym := sym.(*obj.LSym) - if ti, ok := (*lsym.Extra).(*obj.TypeInfo); ok { - if off == 2*c.PtrSize { - return int32(types.TypeHash(ti.Type.(*types.Type))) + if (v.Type.IsPtrShaped() || v.Type.IsUintptr()) && lsym.Type == objabi.SRODATA { + for _, r := range lsym.R { + if (r.Type == objabi.R_ADDR || r.Type == objabi.R_WEAKADDR) && int64(r.Off) == off && r.Add == 0 { + return true + } } + return false } - base.Fatalf("fixed32 data not known for %s:%d", sym, off) - 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") { + if strings.HasPrefix(lsym.Name, "type:") { + // Type symbols do not contain information about their fields, unlike the cases above. + // Hand-implement field accesses. + // TODO: can this be replaced with reflectdata.writeType and just use the code above? + + t := (*lsym.Extra).(*obj.TypeInfo).Type.(*types.Type) + + for _, f := range rttype.Type.Fields() { + if f.Offset == off && copyCompatibleType(v.Type, f.Type) { + switch f.Sym.Name { + case "Hash": return true + default: + // fmt.Println("unknown field", f.Sym.Name) + return false } } } + + if t.IsPtr() && off == rttype.PtrType.OffsetOf("Elem") { + return true + } + + return false } + return false } -func ptrElem(f *Func, sym Sym, off int64) Sym { + +// rewriteFixedLoad rewrites a load to a fixed address or constant, if isFixedLoad returns true. +func rewriteFixedLoad(v *Value, sym Sym, sb *Value, off int64) *Value { + b := v.Block + f := b.Func + 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") { - elemSym := reflectdata.TypeLinksym(t.Elem()) - reflectdata.MarkTypeSymUsedInInterface(elemSym, f.fe.Func().Linksym()) - return elemSym + if (v.Type.IsPtrShaped() || v.Type.IsUintptr()) && lsym.Type == objabi.SRODATA { + for _, r := range lsym.R { + if (r.Type == objabi.R_ADDR || r.Type == objabi.R_WEAKADDR) && int64(r.Off) == off && r.Add == 0 { + if strings.HasPrefix(r.Sym.Name, "type:") { + // In case we're loading a type out of a dictionary, we need to record + // that the containing function might put that type in an interface. + // That information is currently recorded in relocations in the dictionary, + // but if we perform this load at compile time then the dictionary + // might be dead. + reflectdata.MarkTypeSymUsedInInterface(r.Sym, f.fe.Func().Linksym()) + } else if strings.HasPrefix(r.Sym.Name, "go:itab") { + // Same, but if we're using an itab we need to record that the + // itab._type might be put in an interface. + reflectdata.MarkTypeSymUsedInInterface(r.Sym, f.fe.Func().Linksym()) } + v.reset(OpAddr) + v.Aux = symToAux(r.Sym) + v.AddArg(sb) + return v } } + base.Fatalf("fixedLoad data not known for %s:%d", sym, off) } - 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 { - lsym := sym.(*obj.LSym) - switch { - case lsym.Type == objabi.SRODATA: - // itabs, dictionaries - default: - return false - } - for _, r := range lsym.R { - if (r.Type == objabi.R_ADDR || r.Type == objabi.R_WEAKADDR) && int64(r.Off) == off && r.Add == 0 { - return true - } - } - return false -} -func fixedSym(f *Func, sym Sym, off int64) Sym { - lsym := sym.(*obj.LSym) - for _, r := range lsym.R { - if (r.Type == objabi.R_ADDR || r.Type == objabi.R_WEAKADDR) && int64(r.Off) == off { - if strings.HasPrefix(r.Sym.Name, "type:") { - // In case we're loading a type out of a dictionary, we need to record - // that the containing function might put that type in an interface. - // That information is currently recorded in relocations in the dictionary, - // but if we perform this load at compile time then the dictionary - // might be dead. - reflectdata.MarkTypeSymUsedInInterface(r.Sym, f.fe.Func().Linksym()) - } else if strings.HasPrefix(r.Sym.Name, "go:itab") { - // Same, but if we're using an itab we need to record that the - // itab._type might be put in an interface. - reflectdata.MarkTypeSymUsedInInterface(r.Sym, f.fe.Func().Linksym()) + if strings.HasPrefix(lsym.Name, "type:") { + // Type symbols do not contain information about their fields, unlike the cases above. + // Hand-implement field accesses. + // TODO: can this be replaced with reflectdata.writeType and just use the code above? + + t := (*lsym.Extra).(*obj.TypeInfo).Type.(*types.Type) + + for _, f := range rttype.Type.Fields() { + if f.Offset == off && copyCompatibleType(v.Type, f.Type) { + switch f.Sym.Name { + case "Hash": + v.reset(OpConst32) + v.AuxInt = int64(types.TypeHash(t)) + return v + default: + base.Fatalf("unknown field %s for fixedLoad of %s at offset %d", f.Sym.Name, lsym.Name, off) + } } - return r.Sym } + + if t.IsPtr() && off == rttype.PtrType.OffsetOf("Elem") { + elemSym := reflectdata.TypeLinksym(t.Elem()) + reflectdata.MarkTypeSymUsedInInterface(elemSym, f.fe.Func().Linksym()) + v.reset(OpAddr) + v.Aux = symToAux(elemSym) + v.AddArg(sb) + return v + } + + base.Fatalf("fixedLoad data not known for %s:%d", sym, off) } - base.Fatalf("fixedSym data not known for %s:%d", sym, off) + + base.Fatalf("fixedLoad data not known for %s:%d", sym, off) return nil } diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index e776ea5301..28d14e7076 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -14087,8 +14087,6 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - config := b.Func.Config - typ := &b.Func.Config.Types // match: (Load p1 (Store {t2} p2 x _)) // cond: isSamePtr(p1, p2) && copyCompatibleType(t1, x.Type) && t1.Size() == t2.Size() // result: x @@ -14673,344 +14671,26 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { v.AddArg(v0) return true } - // match: (Load (OffPtr [off] (Addr {s} sb) ) _) - // cond: isFixedSym(s, off) - // result: (Addr {fixedSym(b.Func, s, off)} sb) - for { - 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 != 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 (OffPtr [off] (Convert (Addr {s} sb) _) ) _) - // cond: isFixedSym(s, off) - // result: (Addr {fixedSym(b.Func, s, off)} sb) - for { - 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 != 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 (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) - // cond: isFixedSym(s, off) - // result: (Addr {fixedSym(b.Func, s, off)} sb) - for { - 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 != 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 (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.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 (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 (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 (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 (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 - } - v.reset(OpAddr) - v.Aux = symToAux(fixedSym(b.Func, s, off)) - v.AddArg(sb) - return true - } - // match: (Load (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 (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 (ITab (IMake (Addr {s} sb) _)) _) - // cond: isFixedSym(s, 0) - // result: (Addr {fixedSym(b.Func, s, 0)} sb) + // match: (Load (Addr {s} sb) _) + // cond: isFixedLoad(v, s, 0) + // result: rewriteFixedLoad(v, s, sb, 0) 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 (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 (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 { + if v_0.Op != OpAddr { break } s := auxToSym(v_0.Aux) sb := v_0.Args[0] - if !(isFixedSym(s, 0)) { + if !(isFixedLoad(v, s, 0)) { break } - v.reset(OpAddr) - v.Aux = symToAux(fixedSym(b.Func, s, 0)) - v.AddArg(sb) + v.copyOf(rewriteFixedLoad(v, s, sb, 0)) return true } - // match: (Load (Convert (Addr {s} sb) _) _) - // cond: isFixedSym(s, 0) - // result: (Addr {fixedSym(b.Func, s, 0)} sb) + // match: (Load (Convert (Addr {s} sb) _) _) + // cond: isFixedLoad(v, s, 0) + // result: rewriteFixedLoad(v, s, sb, 0) for { - if v.Type != typ.Uintptr || v_0.Op != OpConvert { + if v_0.Op != OpConvert { break } v_0_0 := v_0.Args[0] @@ -15019,19 +14699,17 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { } s := auxToSym(v_0_0.Aux) sb := v_0_0.Args[0] - if !(isFixedSym(s, 0)) { + if !(isFixedLoad(v, s, 0)) { break } - v.reset(OpAddr) - v.Aux = symToAux(fixedSym(b.Func, s, 0)) - v.AddArg(sb) + v.copyOf(rewriteFixedLoad(v, s, sb, 0)) return true } - // match: (Load (ITab (IMake (Addr {s} sb) _)) _) - // cond: isFixedSym(s, 0) - // result: (Addr {fixedSym(b.Func, s, 0)} sb) + // match: (Load (ITab (IMake (Addr {s} sb) _)) _) + // cond: isFixedLoad(v, s, 0) + // result: rewriteFixedLoad(v, s, sb, 0) for { - if v.Type != typ.Uintptr || v_0.Op != OpITab { + if v_0.Op != OpITab { break } v_0_0 := v_0.Args[0] @@ -15044,19 +14722,17 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { } s := auxToSym(v_0_0_0.Aux) sb := v_0_0_0.Args[0] - if !(isFixedSym(s, 0)) { + if !(isFixedLoad(v, s, 0)) { break } - v.reset(OpAddr) - v.Aux = symToAux(fixedSym(b.Func, s, 0)) - v.AddArg(sb) + v.copyOf(rewriteFixedLoad(v, s, sb, 0)) return true } - // match: (Load (ITab (IMake (Convert (Addr {s} sb) _) _)) _) - // cond: isFixedSym(s, 0) - // result: (Addr {fixedSym(b.Func, s, 0)} sb) + // match: (Load (ITab (IMake (Convert (Addr {s} sb) _) _)) _) + // cond: isFixedLoad(v, s, 0) + // result: rewriteFixedLoad(v, s, sb, 0) for { - if v.Type != typ.Uintptr || v_0.Op != OpITab { + if v_0.Op != OpITab { break } v_0_0 := v_0.Args[0] @@ -15073,19 +14749,16 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { } s := auxToSym(v_0_0_0_0.Aux) sb := v_0_0_0_0.Args[0] - if !(isFixedSym(s, 0)) { + if !(isFixedLoad(v, s, 0)) { break } - v.reset(OpAddr) - v.Aux = symToAux(fixedSym(b.Func, s, 0)) - v.AddArg(sb) + v.copyOf(rewriteFixedLoad(v, s, sb, 0)) return true } - // match: (Load (OffPtr [off] (Addr {s} sb) ) _) - // cond: t.IsPtr() && isPtrElem(s, off) - // result: (Addr {ptrElem(b.Func, s, off)} sb) + // match: (Load (OffPtr [off] (Addr {s} sb) ) _) + // cond: isFixedLoad(v, s, off) + // result: rewriteFixedLoad(v, s, sb, off) for { - t := v.Type if v_0.Op != OpOffPtr { break } @@ -15096,19 +14769,16 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { } s := auxToSym(v_0_0.Aux) sb := v_0_0.Args[0] - if !(t.IsPtr() && isPtrElem(s, off)) { + if !(isFixedLoad(v, s, off)) { break } - v.reset(OpAddr) - v.Aux = symToAux(ptrElem(b.Func, s, off)) - v.AddArg(sb) + v.copyOf(rewriteFixedLoad(v, s, sb, off)) return true } - // match: (Load (OffPtr [off] (Convert (Addr {s} sb) _) ) _) - // cond: t.IsPtr() && isPtrElem(s, off) - // result: (Addr {ptrElem(b.Func, s, off)} sb) + // match: (Load (OffPtr [off] (Convert (Addr {s} sb) _) ) _) + // cond: isFixedLoad(v, s, off) + // result: rewriteFixedLoad(v, s, sb, off) for { - t := v.Type if v_0.Op != OpOffPtr { break } @@ -15123,19 +14793,16 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { } s := auxToSym(v_0_0_0.Aux) sb := v_0_0_0.Args[0] - if !(t.IsPtr() && isPtrElem(s, off)) { + if !(isFixedLoad(v, s, off)) { break } - v.reset(OpAddr) - v.Aux = symToAux(ptrElem(b.Func, s, off)) - v.AddArg(sb) + v.copyOf(rewriteFixedLoad(v, s, sb, off)) return true } - // match: (Load (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) - // cond: t.IsPtr() && isPtrElem(s, off) - // result: (Addr {ptrElem(b.Func, s, off)} sb) + // match: (Load (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) + // cond: isFixedLoad(v, s, off) + // result: rewriteFixedLoad(v, s, sb, off) for { - t := v.Type if v_0.Op != OpOffPtr { break } @@ -15154,19 +14821,16 @@ func rewriteValuegeneric_OpLoad(v *Value) bool { } s := auxToSym(v_0_0_0_0.Aux) sb := v_0_0_0_0.Args[0] - if !(t.IsPtr() && isPtrElem(s, off)) { + if !(isFixedLoad(v, s, off)) { break } - v.reset(OpAddr) - v.Aux = symToAux(ptrElem(b.Func, s, off)) - v.AddArg(sb) + v.copyOf(rewriteFixedLoad(v, s, sb, off)) return true } - // match: (Load (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) - // cond: t.IsPtr() && isPtrElem(s, off) - // result: (Addr {ptrElem(b.Func, s, off)} sb) + // match: (Load (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) + // cond: isFixedLoad(v, s, off) + // result: rewriteFixedLoad(v, s, sb, off) for { - t := v.Type if v_0.Op != OpOffPtr { break } @@ -15189,120 +14853,10 @@ 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.IsPtr() && isPtrElem(s, off)) { - break - } - v.reset(OpAddr) - v.Aux = symToAux(ptrElem(b.Func, s, off)) - v.AddArg(sb) - return true - } - // match: (Load (OffPtr [off] (Addr {sym} _) ) _) - // cond: t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) - // result: (Const32 [fixed32(config, sym, off)]) - 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 - } - sym := auxToSym(v_0_0.Aux) - if !(t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off)) { - break - } - v.reset(OpConst32) - v.AuxInt = int32ToAuxInt(fixed32(config, sym, off)) - return true - } - // match: (Load (OffPtr [off] (Convert (Addr {sym} _) _) ) _) - // cond: t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) - // result: (Const32 [fixed32(config, sym, off)]) - for { - t := v.Type - if v_0.Op != OpOffPtr { + if !(isFixedLoad(v, s, off)) { 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 - } - sym := auxToSym(v_0_0_0.Aux) - if !(t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off)) { - break - } - v.reset(OpConst32) - v.AuxInt = int32ToAuxInt(fixed32(config, sym, off)) - return true - } - // match: (Load (OffPtr [off] (ITab (IMake (Addr {sym} _) _))) _) - // cond: t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) - // result: (Const32 [fixed32(config, sym, off)]) - 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 - } - sym := auxToSym(v_0_0_0_0.Aux) - if !(t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off)) { - break - } - v.reset(OpConst32) - v.AuxInt = int32ToAuxInt(fixed32(config, sym, off)) - return true - } - // match: (Load (OffPtr [off] (ITab (IMake (Convert (Addr {sym} _) _) _))) _) - // cond: t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) - // result: (Const32 [fixed32(config, sym, off)]) - 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 - } - sym := auxToSym(v_0_0_0_0_0.Aux) - if !(t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off)) { - break - } - v.reset(OpConst32) - v.AuxInt = int32ToAuxInt(fixed32(config, sym, off)) + v.copyOf(rewriteFixedLoad(v, s, sb, off)) return true } return false