Skip to content

Commit 875332b

Browse files
committed
cmd/compile/internal: merge stack slots for selected local auto vars
[This is a partial roll-forward of CL 553055, the main change here is that the stack slot overlap operation is flagged off by default (can be enabled by hand with -gcflags=-d=mergelocals=1) ] Preliminary compiler support for merging/overlapping stack slots of local variables whose access patterns are disjoint. This patch includes changes in AllocFrame to do the actual merging/overlapping based on information returned from a new liveness.MergeLocals helper. The MergeLocals helper identifies candidates by looking for sets of AUTO variables that either A) have the same size and GC shape (if types contain pointers), or B) have the same size (but potentially different types as long as those types have no pointers). Variables must be greater than (3*types.PtrSize) in size to be considered for merging. After forming candidates, MergeLocals collects variables into "can be overlapped" equivalence classes or partitions; this process is driven by an additional liveness analysis pass. Ideally it would be nice to move the existing stackmap liveness pass up before AllocFrame and "widen" it to include merge candidates so that we can do just a single liveness as opposed to two passes, however this may be difficult given that the merge-locals liveness has to take into account writes corresponding to dead stores. This patch also required a change to the way ssa.OpVarDef pseudo-ops are generated; prior to this point they would only be created for variables whose type included pointers; if stack slot merging is enabled then the ssagen code creates OpVarDef ops for all auto vars that are merge candidates. Note that some temporaries created late in the compilation process (e.g. during ssa backend) are difficult to reason about, especially in cases where we take the address of a temp and pass it to the runtime. For the time being we mark most of the vars created post-ssagen as "not a merge candidate". Stack slot merging for locals/autos is enabled by default if "-N" is not in effect, and can be disabled via "-gcflags=-d=mergelocals=0". Fixmes/todos/restrictions: - try lowering size restrictions - re-evaluate the various skips that happen in SSA-created autotmps Updates #62737. Updates #65532. Updates #65495. Change-Id: Ifda26bc48cde5667de245c8a9671b3f0a30bb45d Reviewed-on: https://go-review.googlesource.com/c/go/+/575415 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent de3a3c9 commit 875332b

File tree

14 files changed

+1511
-222
lines changed

14 files changed

+1511
-222
lines changed

src/cmd/compile/internal/base/debug.go

+4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ type DebugFlags struct {
4141
LoopVarHash string `help:"for debugging changes in loop behavior. Overrides experiment and loopvar flag."`
4242
LocationLists int `help:"print information about DWARF location list creation"`
4343
MaxShapeLen int `help:"hash shape names longer than this threshold (default 500)" concurrent:"ok"`
44+
MergeLocals int `help:"merge together non-interfering local stack slots" concurrent:"ok"`
45+
MergeLocalsDumpFunc string `help:"dump specified func in merge locals"`
46+
MergeLocalsHash string `help:"hash value for debugging stack slot merging of local variables" concurrent:"ok"`
47+
MergeLocalsTrace int `help:"trace debug output for locals merging"`
4448
Nil int `help:"print information about nil checks"`
4549
NoOpenDefer int `help:"disable open-coded defers" concurrent:"ok"`
4650
NoRefName int `help:"do not include referenced symbol names in object file" concurrent:"ok"`

src/cmd/compile/internal/base/flag.go

+3
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ func ParseFlags() {
260260
if Debug.PGOHash != "" {
261261
PGOHash = NewHashDebug("pgohash", Debug.PGOHash, nil)
262262
}
263+
if Debug.MergeLocalsHash != "" {
264+
MergeLocalsHash = NewHashDebug("mergelocals", Debug.MergeLocalsHash, nil)
265+
}
263266

264267
if Flag.MSan && !platform.MSanSupported(buildcfg.GOOS, buildcfg.GOARCH) {
265268
log.Fatalf("%s/%s does not support -msan", buildcfg.GOOS, buildcfg.GOARCH)

src/cmd/compile/internal/base/hashdebug.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ func (d *HashDebug) SetInlineSuffixOnly(b bool) *HashDebug {
5353
// The default compiler-debugging HashDebug, for "-d=gossahash=..."
5454
var hashDebug *HashDebug
5555

56-
var FmaHash *HashDebug // for debugging fused-multiply-add floating point changes
57-
var LoopVarHash *HashDebug // for debugging shared/private loop variable changes
58-
var PGOHash *HashDebug // for debugging PGO optimization decisions
56+
var FmaHash *HashDebug // for debugging fused-multiply-add floating point changes
57+
var LoopVarHash *HashDebug // for debugging shared/private loop variable changes
58+
var PGOHash *HashDebug // for debugging PGO optimization decisions
59+
var MergeLocalsHash *HashDebug // for debugging local stack slot merging changes
5960

6061
// DebugHashMatchPkgFunc reports whether debug variable Gossahash
6162
//

src/cmd/compile/internal/ir/name.go

+3
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ const (
194194
nameLibfuzzer8BitCounter // if PEXTERN should be assigned to __sancov_cntrs section
195195
nameCoverageAuxVar // instrumentation counter var or pkg ID for cmd/cover
196196
nameAlias // is type name an alias
197+
nameNonMergeable // not a candidate for stack slot merging
197198
)
198199

199200
func (n *Name) Readonly() bool { return n.flags&nameReadonly != 0 }
@@ -209,6 +210,7 @@ func (n *Name) InlLocal() bool { return n.flags&nameInlLocal !=
209210
func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 }
210211
func (n *Name) Libfuzzer8BitCounter() bool { return n.flags&nameLibfuzzer8BitCounter != 0 }
211212
func (n *Name) CoverageAuxVar() bool { return n.flags&nameCoverageAuxVar != 0 }
213+
func (n *Name) NonMergeable() bool { return n.flags&nameNonMergeable != 0 }
212214

213215
func (n *Name) setReadonly(b bool) { n.flags.set(nameReadonly, b) }
214216
func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) }
@@ -223,6 +225,7 @@ func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b
223225
func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) }
224226
func (n *Name) SetLibfuzzer8BitCounter(b bool) { n.flags.set(nameLibfuzzer8BitCounter, b) }
225227
func (n *Name) SetCoverageAuxVar(b bool) { n.flags.set(nameCoverageAuxVar, b) }
228+
func (n *Name) SetNonMergeable(b bool) { n.flags.set(nameNonMergeable, b) }
226229

227230
// OnStack reports whether variable n may reside on the stack.
228231
func (n *Name) OnStack() bool {

0 commit comments

Comments
 (0)