]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/escape: add debug hash for literal allocation optimizations
authorthepudds <thepudds1460@gmail.com>
Sat, 28 Jun 2025 20:53:37 +0000 (16:53 -0400)
committert hepudds <thepudds1460@gmail.com>
Mon, 30 Jun 2025 21:01:43 +0000 (14:01 -0700)
Several CLs earlier in this stack added optimizations to reduce
user allocations by recognizing and taking advantage of literals,
including CL 649555, CL 649079, and CL 649035.

This CL adds debug hashing of those changes, which enables use of the
bisect tool, such as 'bisect -compile=literalalloc go test -run=Foo'.
This also allows these optimizations to be manually disabled via
'-gcflags=all=-d=literalallochash=n'.

Updates #71359

Change-Id: I854f7742a6efa5b17d914932d61a32b2297f0c88
Reviewed-on: https://go-review.googlesource.com/c/go/+/675415
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/compile/internal/base/debug.go
src/cmd/compile/internal/base/flag.go
src/cmd/compile/internal/base/hashdebug.go
src/cmd/compile/internal/escape/escape.go
src/cmd/compile/internal/walk/order.go

index 10393e773c366dceda48afada81600b3aac440c6..85873dcc40e1b31279c9c8b20cb4df3efcb75130 100644 (file)
@@ -40,6 +40,7 @@ type DebugFlags struct {
        InlFuncsWithClosures  int    `help:"allow functions with closures to be inlined" concurrent:"ok"`
        InlStaticInit         int    `help:"allow static initialization of inlined calls" concurrent:"ok"`
        Libfuzzer             int    `help:"enable coverage instrumentation for libfuzzer"`
+       LiteralAllocHash      string `help:"hash value for use in debugging literal allocation optimizations" concurrent:"ok"`
        LoopVar               int    `help:"shared (0, default), 1 (private loop variables), 2, private + log"`
        LoopVarHash           string `help:"for debugging changes in loop behavior. Overrides experiment and loopvar flag."`
        LocationLists         int    `help:"print information about DWARF location list creation"`
index abf85c7e7869dbaf31b671d9eda3a9b476a1ebed..e87f57cdaae0206d55f1d238a8cafe57a859fe6f 100644 (file)
@@ -268,6 +268,10 @@ func ParseFlags() {
        if Debug.PGOHash != "" {
                PGOHash = NewHashDebug("pgohash", Debug.PGOHash, nil)
        }
+       if Debug.LiteralAllocHash != "" {
+               LiteralAllocHash = NewHashDebug("literalalloc", Debug.LiteralAllocHash, nil)
+       }
+
        if Debug.MergeLocalsHash != "" {
                MergeLocalsHash = NewHashDebug("mergelocals", Debug.MergeLocalsHash, nil)
        }
index c54b6e17aae2f0aa0d572c433578afbedac81a01..fa63deb46a3c019bde47b683a4d7b6e3ef882db6 100644 (file)
@@ -56,6 +56,7 @@ var hashDebug *HashDebug
 var FmaHash *HashDebug          // for debugging fused-multiply-add floating point changes
 var LoopVarHash *HashDebug      // for debugging shared/private loop variable changes
 var PGOHash *HashDebug          // for debugging PGO optimization decisions
+var LiteralAllocHash *HashDebug // for debugging literal allocation optimizations
 var MergeLocalsHash *HashDebug  // for debugging local stack slot merging changes
 var VariableMakeHash *HashDebug // for debugging variable-sized make optimizations
 
index 600b986d3fbdddf97db668b68d5881f6df9892be..72d40bd258d8f13155019d36cf3fbedb123922b9 100644 (file)
@@ -567,6 +567,10 @@ func (b *batch) rewriteWithLiterals(n ir.Node, fn *ir.Func) {
                                        base.Fatalf("unexpected BasicLit Kind")
                                }
                                if constant.Compare(lit.Val(), token.GEQ, constant.MakeInt64(0)) {
+                                       if !base.LiteralAllocHash.MatchPos(n.Pos(), nil) {
+                                               // De-selected by literal alloc optimizations debug hash.
+                                               return
+                                       }
                                        // Preserve any side effects of the original expression, then replace it.
                                        assignTemp(*r, n.PtrInit())
                                        *r = lit
@@ -580,6 +584,10 @@ func (b *batch) rewriteWithLiterals(n ir.Node, fn *ir.Func) {
                if conv.X.Op() != ir.OLITERAL && !conv.X.Type().IsInterface() {
                        v := ro.StaticValue(conv.X)
                        if v != nil && v.Op() == ir.OLITERAL && ir.ValidTypeForConst(conv.X.Type(), v.Val()) {
+                               if !base.LiteralAllocHash.MatchPos(n.Pos(), nil) {
+                                       // De-selected by literal alloc optimizations debug hash.
+                                       return
+                               }
                                if base.Debug.EscapeDebug >= 3 {
                                        base.WarnfAt(n.Pos(), "rewriting OCONVIFACE value from %v (%v) to %v (%v)", conv.X, conv.X.Type(), v, v.Type())
                                }
index 8ba8dd96cc41c6241a4bec36e5a931d00cf0babc..cb022faddf29e3d1f7dc32e479fba7e0654dfa27 100644 (file)
@@ -246,14 +246,18 @@ func (o *orderState) addrTemp(n ir.Node) ir.Node {
        if v == nil {
                v = n
        }
+       optEnabled := func(n ir.Node) bool {
+               // Do this optimization only when enabled for this node.
+               return base.LiteralAllocHash.MatchPos(n.Pos(), nil)
+       }
        if (v.Op() == ir.OSTRUCTLIT || v.Op() == ir.OARRAYLIT) && !base.Ctxt.IsFIPS() {
-               if ir.IsZero(v) && 0 < v.Type().Size() && v.Type().Size() <= abi.ZeroValSize {
+               if ir.IsZero(v) && 0 < v.Type().Size() && v.Type().Size() <= abi.ZeroValSize && optEnabled(n) {
                        // This zero value can be represented by the read-only zeroVal.
                        zeroVal := ir.NewLinksymExpr(v.Pos(), ir.Syms.ZeroVal, n.Type())
                        vstat := typecheck.Expr(zeroVal).(*ir.LinksymOffsetExpr)
                        return vstat
                }
-               if isStaticCompositeLiteral(v) {
+               if isStaticCompositeLiteral(v) && optEnabled(n) {
                        // v can be directly represented in the read-only data section.
                        lit := v.(*ir.CompLitExpr)
                        vstat := readonlystaticname(n.Type())