1
0
mirror of https://github.com/golang/go synced 2024-11-07 07:36:14 -07:00

cmd/compile: tighten for huge functions in -N mode

Currently, in -N mode we skip the tighten pass. However, for very
large functions, many values live across blocks can cause
pathological behavior in the register allocator, which could use
a huge amount of memory or cause the program to hang. For
functions that large, debugging using a debugger is unlikely to be
very useful (the function is probably generated anyway). So we do
a little optimization to make fewer values live across blocks and
make it easier for the compiler.

Fixes #52180.

Change-Id: I355fe31bb87ea5d0870bb52dd06405dd5d791dab
Reviewed-on: https://go-review.googlesource.com/c/go/+/475339
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Cherry Mui 2023-03-10 16:28:57 -05:00
parent 7f38067acb
commit 40a6e2dae5
2 changed files with 10 additions and 1 deletions

View File

@ -496,7 +496,7 @@ var passes = [...]pass{
{name: "checkLower", fn: checkLower, required: true},
{name: "late phielim", fn: phielim},
{name: "late copyelim", fn: copyelim},
{name: "tighten", fn: tighten}, // move values closer to their uses
{name: "tighten", fn: tighten, required: true}, // move values closer to their uses
{name: "late deadcode", fn: deadcode},
{name: "critical", fn: critical, required: true}, // remove critical edges
{name: "phi tighten", fn: phiTighten}, // place rematerializable phi args near uses to reduce value lifetimes

View File

@ -4,12 +4,21 @@
package ssa
import "cmd/compile/internal/base"
// tighten moves Values closer to the Blocks in which they are used.
// This can reduce the amount of register spilling required,
// if it doesn't also create more live values.
// A Value can be moved to any block that
// dominates all blocks in which it is used.
func tighten(f *Func) {
if base.Flag.N != 0 && len(f.Blocks) < 10000 {
// Skip the optimization in -N mode, except for huge functions.
// Too many values live across blocks can cause pathological
// behavior in the register allocator (see issue 52180).
return
}
canMove := f.Cache.allocBoolSlice(f.NumValues())
defer f.Cache.freeBoolSlice(canMove)
for _, b := range f.Blocks {