wazevo: adds tests for high register pressure (#1686)

Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
This commit is contained in:
Takeshi Yoneda
2023-09-05 10:37:36 +09:00
committed by GitHub
parent 30e1b58e6a
commit 405a5c9dac
16 changed files with 160 additions and 85 deletions

View File

@@ -1,6 +1,7 @@
package backend_test
import (
"context"
"encoding/hex"
"fmt"
"os"
@@ -80,10 +81,14 @@ L1 (SSA Block: blk0):
name: "consts", m: testcases.Constants.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
ldr d1, #8; b 16; data.f64 64.000000
ldr s0, #8; b 8; data.f32 32.000000
orr x1, xzr, #0x2
orr w0, wzr, #0x1
ldr d5?, #8; b 16; data.f64 64.000000
mov v1.8b, v5?.8b
ldr s4?, #8; b 8; data.f32 32.000000
mov v0.8b, v4?.8b
orr x3?, xzr, #0x2
mov x1, x3?
orr w2?, wzr, #0x1
mov x0, x2?
ret
`,
afterFinalizeARM64: `
@@ -169,7 +174,8 @@ L1 (SSA Block: blk0):
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x1, xzr
mov x3?, xzr
mov x1, x3?
mov x0, x2?
ret
`,
@@ -411,10 +417,12 @@ L1 (SSA Block: blk0):
cbnz w4?, L2
L3 (SSA Block: blk2):
L4 (SSA Block: blk3):
mov x0, xzr
mov x2?, xzr
mov x0, x2?
ret
L2 (SSA Block: blk1):
mov x0, xzr
mov x3?, xzr
mov x0, x3?
ret
`,
afterFinalizeARM64: `
@@ -493,7 +501,8 @@ L4 (SSA Block: blk5):
L3 (SSA Block: blk4):
L5 (SSA Block: blk3):
L6 (SSA Block: blk2):
mov x0, xzr
mov x3?, xzr
mov x0, x3?
ret
`,
afterFinalizeARM64: `
@@ -2974,27 +2983,33 @@ L2 (SSA Block: blk7):
b L9
L3 (SSA Block: blk8):
L10 (SSA Block: blk5):
orr w0, wzr, #0xc
orr w3?, wzr, #0xc
mov x0, x3?
ret
L4 (SSA Block: blk9):
L11 (SSA Block: blk4):
movz w0, #0xd, lsl 0
movz w4?, #0xd, lsl 0
mov x0, x4?
ret
L5 (SSA Block: blk10):
L12 (SSA Block: blk3):
orr w0, wzr, #0xe
orr w5?, wzr, #0xe
mov x0, x5?
ret
L6 (SSA Block: blk11):
L13 (SSA Block: blk2):
orr w0, wzr, #0xf
orr w6?, wzr, #0xf
mov x0, x6?
ret
L7 (SSA Block: blk12):
L14 (SSA Block: blk1):
orr w0, wzr, #0x10
orr w7?, wzr, #0x10
mov x0, x7?
ret
L8 (SSA Block: blk13):
L9 (SSA Block: blk6):
movz w0, #0xb, lsl 0
movz w8?, #0xb, lsl 0
mov x0, x8?
ret
`,
afterFinalizeARM64: `
@@ -3045,7 +3060,7 @@ L9 (SSA Block: blk6):
fc := frontend.NewFrontendCompiler(tc.m, ssab, &offset)
machine := newMachine()
machine.DisableStackCheck()
be := backend.NewCompiler(machine, ssab)
be := backend.NewCompiler(context.Background(), machine, ssab)
// Lowers the Wasm to SSA.
typeIndex := tc.m.FunctionSection[tc.targetIndex]

View File

@@ -11,18 +11,23 @@ import (
)
// NewCompiler returns a new Compiler that can generate a machine code.
func NewCompiler(mach Machine, builder ssa.Builder) Compiler {
return newCompiler(mach, builder)
func NewCompiler(ctx context.Context, mach Machine, builder ssa.Builder) Compiler {
return newCompiler(ctx, mach, builder)
}
func newCompiler(mach Machine, builder ssa.Builder) *compiler {
func newCompiler(ctx context.Context, mach Machine, builder ssa.Builder) *compiler {
registerSetDebug := false
if wazevoapi.RegAllocValidationEnabled {
registerSetDebug = wazevoapi.IsHighRegisterPressure(ctx)
}
c := &compiler{
mach: mach, ssaBuilder: builder,
alreadyLowered: make(map[*ssa.Instruction]bool),
vRegSet: make(map[regalloc.VReg]bool),
ssaTypeOfVRegID: make(map[regalloc.VRegID]ssa.Type),
nextVRegID: 0,
regAlloc: regalloc.NewAllocator(mach.RegisterInfo()),
regAlloc: regalloc.NewAllocator(mach.RegisterInfo(registerSetDebug)),
}
mach.SetCompiler(c)
return c
@@ -147,21 +152,21 @@ type compiler struct {
func (c *compiler) Compile(ctx context.Context) ([]byte, []RelocationInfo, int, error) {
c.Lower()
if wazevoapi.PrintSSAToBackendIRLowering {
fmt.Printf("[[[after lowering]]]%s\n", c.Format())
fmt.Printf("[[[after lowering for %s ]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), c.Format())
}
if wazevoapi.DeterministicCompilationVerifierEnabled {
wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "After lowering to ISA specific IR", c.Format())
}
c.RegAlloc()
if wazevoapi.PrintRegisterAllocated {
fmt.Printf("[[[after regalloc]]]%s\n", c.Format())
fmt.Printf("[[[after regalloc for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), c.Format())
}
if wazevoapi.DeterministicCompilationVerifierEnabled {
wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "After Register Allocation", c.Format())
}
c.Finalize()
if wazevoapi.PrintFinalizedMachineCode {
fmt.Printf("[[[after finalize]]]%s\n", c.Format())
fmt.Printf("[[[after finalize for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), c.Format())
}
if wazevoapi.DeterministicCompilationVerifierEnabled {
wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "After Finalization", c.Format())

View File

@@ -1,6 +1,7 @@
package backend
import (
"context"
"testing"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
@@ -51,7 +52,7 @@ func TestCompiler_lowerBlockArguments(t *testing.T) {
},
}
c := newCompiler(m, builder)
c := newCompiler(context.Background(), m, builder)
c.ssaValueDefinitions = []SSAValueDefinition{{Instr: i1}, {Instr: i2}, {Instr: f1}, {Instr: f2}}
c.ssaValueToVRegs = []regalloc.VReg{0, 1, 2, 3, 4, 5, 6, 7}
return c, []ssa.Value{i1.Return(), i2.Return(), f1.Return(), f2.Return()}, succ, func(t *testing.T) {
@@ -79,7 +80,7 @@ func TestCompiler_lowerBlockArguments(t *testing.T) {
m := &mockMachine{insertMove: func(dst, src regalloc.VReg) {
insertMoves = append(insertMoves, struct{ src, dst regalloc.VReg }{src: src, dst: dst})
}}
c := newCompiler(m, builder)
c := newCompiler(context.Background(), m, builder)
c.ssaValueDefinitions = []SSAValueDefinition{{}, {}, {}, {}}
c.ssaValueToVRegs = []regalloc.VReg{0, 1, 2, 3}
c.nextVRegID = 100 // Temporary reg should start with 100.
@@ -117,7 +118,7 @@ func TestCompiler_lowerBlockArguments(t *testing.T) {
m := &mockMachine{insertMove: func(dst, src regalloc.VReg) {
insertMoves = append(insertMoves, struct{ src, dst regalloc.VReg }{src: src, dst: dst})
}}
c := newCompiler(m, builder)
c := newCompiler(context.Background(), m, builder)
c.ssaValueDefinitions = []SSAValueDefinition{{}, {}}
c.ssaValueToVRegs = []regalloc.VReg{0, 1}
return c, []ssa.Value{add.Return()}, blk, func(t *testing.T) {

View File

@@ -210,8 +210,7 @@ func (a *abiImpl) CalleeGenVRegsToFunctionReturns(rets []ssa.Value) {
if def := a.m.compiler.ValueDefinition(ret); def.IsFromInstr() {
// Constant instructions are inlined.
if inst := def.Instr; inst.Constant() {
a.m.InsertLoadConstant(inst, r.Reg)
continue
a.m.InsertLoadConstant(inst, reg)
}
}
if r.Kind == backend.ABIArgKindReg {

View File

@@ -1761,11 +1761,17 @@ func (i *instruction) size() int64 {
case nop0:
return 0
case loadFpuConst32:
if i.u1 == 0 {
return 4 // zero loading can be encoded as a single instruction.
}
return 4 + 4 + 4
case loadFpuConst64:
if i.u1 == 0 {
return 4 // zero loading can be encoded as a single instruction.
}
return 4 + 4 + 8
case loadFpuConst128:
return 4 + 4 + 12
panic("TODO")
case brTableSequence:
return 4*4 + int64(len(i.targets))*4
default:

View File

@@ -106,9 +106,19 @@ func (i *instruction) encode(c backend.Compiler) {
}
c.Emit4Bytes(encodePreOrPostIndexLoadStorePair64(pre, kind == loadP64, rn, rt, rt2, amode.imm))
case loadFpuConst32:
encodeLoadFpuConst32(c, regNumberInEncoding[i.rd.realReg()], i.u1)
rd := regNumberInEncoding[i.rd.realReg()]
if i.u1 == 0 {
c.Emit4Bytes(encodeVecRRR(vecOpEOR, rd, rd, rd, vecArrangement8B))
} else {
encodeLoadFpuConst32(c, rd, i.u1)
}
case loadFpuConst64:
encodeLoadFpuConst64(c, regNumberInEncoding[i.rd.realReg()], i.u1)
rd := regNumberInEncoding[i.rd.realReg()]
if i.u1 == 0 {
c.Emit4Bytes(encodeVecRRR(vecOpEOR, rd, rd, rd, vecArrangement8B))
} else {
encodeLoadFpuConst64(c, regNumberInEncoding[i.rd.realReg()], i.u1)
}
case aluRRRR:
c.Emit4Bytes(encodeAluRRRR(
aluOp(i.u1),
@@ -591,7 +601,7 @@ func encodeLoadFpuConst32(c backend.Compiler, rd uint32, rawF32 uint64) {
// encodeLoadFpuConst64 encodes the following three instructions:
//
// ldr x8, #8 ;; literal load of data.f64
// ldr d8, #8 ;; literal load of data.f64
// b 12 ;; skip the data
// data.f64 xxxxxxx
func encodeLoadFpuConst64(c backend.Compiler, rd uint32, rawF64 uint64) {

View File

@@ -178,9 +178,11 @@ func TestInstruction_encode(t *testing.T) {
}},
{want: "30000010", setup: func(i *instruction) { i.asAdr(v16VReg, 4) }},
{want: "50050030", setup: func(i *instruction) { i.asAdr(v16VReg, 169) }},
{want: "101e302e", setup: func(i *instruction) { i.asLoadFpuConst32(v16VReg, uint64(math.Float32bits(0))) }},
{want: "5000001c020000140000803f", setup: func(i *instruction) {
i.asLoadFpuConst32(v16VReg, uint64(math.Float32bits(1.0)))
}},
{want: "101e302e", setup: func(i *instruction) { i.asLoadFpuConst64(v16VReg, uint64(math.Float32bits(0))) }},
{want: "5000005c03000014000000000000f03f", setup: func(i *instruction) {
i.asLoadFpuConst64(v16VReg, math.Float64bits(1.0))
}},

View File

@@ -28,21 +28,11 @@ func (m *machine) InsertLoadConstant(instr *ssa.Instruction, vr regalloc.VReg) {
switch valType {
case ssa.TypeF32:
loadF := m.allocateInstr()
if v == 0 {
// Fast path for zero. Use v30VReg (least likely to be allocated real register) so that we don't put pressure on the register allocator.
loadF.asVecRRR(vecOpEOR, operandNR(vr), operandNR(v30VReg), operandNR(v30VReg), vecArrangement8B)
} else {
loadF.asLoadFpuConst32(vr, v)
}
loadF.asLoadFpuConst32(vr, v)
m.insert(loadF)
case ssa.TypeF64:
loadF := m.allocateInstr()
if v == 0 {
// Fast path for zero. Use v30VReg (least likely to be allocated real register) so that we don't put pressure on the register allocator.
loadF.asVecRRR(vecOpEOR, operandNR(vr), operandNR(v30VReg), operandNR(v30VReg), vecArrangement8B)
} else {
loadF.asLoadFpuConst64(vr, v)
}
loadF.asLoadFpuConst64(vr, v)
m.insert(loadF)
case ssa.TypeI32:
if v == 0 {

View File

@@ -220,7 +220,20 @@ func (r *regAllocInstrImpl) IsCopy() bool {
}
// RegisterInfo implements backend.Machine.
func (m *machine) RegisterInfo() *regalloc.RegisterInfo {
func (m *machine) RegisterInfo(debug bool) *regalloc.RegisterInfo {
if debug {
regInfoDebug := &regalloc.RegisterInfo{}
regInfoDebug.CalleeSavedRegisters = regInfo.CalleeSavedRegisters
regInfoDebug.CallerSavedRegisters = regInfo.CallerSavedRegisters
regInfoDebug.RealRegToVReg = regInfo.RealRegToVReg
regInfoDebug.RealRegName = regInfo.RealRegName
regInfoDebug.AllocatableRegisters[regalloc.RegTypeFloat] = []regalloc.RealReg{
v7, v6, v5, v4, v3, v2, v1, v0, // Allocatable sets == Argument registers.
}
// TODO: tests for high pressured int registers.
regInfoDebug.AllocatableRegisters[regalloc.RegTypeInt] = regInfo.AllocatableRegisters[regalloc.RegTypeInt]
return regInfoDebug
}
return regInfo
}

View File

@@ -25,7 +25,7 @@ func formatEmittedInstructionsInCurrentBlock(m *machine) string {
func newSetup() (ssa.Builder, *machine) {
m := NewBackend().(*machine)
ssaB := ssa.NewBuilder()
backend.NewCompiler(m, ssaB)
backend.NewCompiler(context.Background(), m, ssaB)
blk := ssaB.AllocateBasicBlock()
ssaB.SetCurrentBlock(blk)
return ssaB, m

View File

@@ -14,7 +14,9 @@ type (
// RegisterInfo returns the set of registers that can be used for register allocation.
// This is only called once, and the result is shared across all compilations.
RegisterInfo() *regalloc.RegisterInfo
//
// If debug is true, this returns the register set for debugging purpose.
RegisterInfo(debug bool) *regalloc.RegisterInfo
// InitializeABI initializes the FunctionABI for the given signature.
InitializeABI(sig *ssa.Signature)

View File

@@ -52,7 +52,7 @@ func (m mockMachine) ResolveRelativeAddresses() {}
func (m mockMachine) Function() (f regalloc.Function) { return }
// RegisterInfo implements Machine.RegisterInfo.
func (m mockMachine) RegisterInfo() *regalloc.RegisterInfo {
func (m mockMachine) RegisterInfo(bool) *regalloc.RegisterInfo {
if m.rinfo != nil {
return m.rinfo
}

View File

@@ -55,8 +55,10 @@ type (
// Allocator is a register allocator.
Allocator struct {
// regInfo is static per ABI/ISA, and is initialized by the machine during Machine.PrepareRegisterAllocator.
regInfo *RegisterInfo
allocatableSet map[RealReg]struct{}
regInfo *RegisterInfo
// allocatableSet is a set of allocatable RealReg derived from regInfo. Static per ABI/ISA.
allocatableSet map[RealReg]struct{}
// allocatedRegSet is a set of RealReg that are allocated during the allocation phase. This is reset per function.
allocatedRegSet map[RealReg]struct{}
allocatedCalleeSavedRegs []VReg
nodePool wazevoapi.Pool[node]
@@ -473,13 +475,6 @@ func (a *Allocator) Reset() {
a.vRegIDToNode[i] = nil
}
rr := a.realRegs[:0]
for r := range a.allocatableSet {
rr = append(rr, r)
}
for _, r := range rr {
delete(a.allocatableSet, r)
}
rr = rr[:0]
for r := range a.allocatedRegSet {
rr = append(rr, r)
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/engine/wazevo"
"github.com/tetratelabs/wazero/internal/engine/wazevo/testcases"
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
"github.com/tetratelabs/wazero/internal/filecache"
"github.com/tetratelabs/wazero/internal/integration_test/spectest"
v1 "github.com/tetratelabs/wazero/internal/integration_test/spectest/v1"
@@ -108,8 +109,15 @@ func TestSpectestV1(t *testing.T) {
{name: "unwind"},
} {
t.Run(tc.name, func(t *testing.T) {
spectest.RunCase(t, v1.Testcases, tc.name, context.Background(), config,
-1, 0, math.MaxInt)
t.Run("normal", func(t *testing.T) {
spectest.RunCase(t, v1.Testcases, tc.name, context.Background(), config,
-1, 0, math.MaxInt)
})
t.Run("reg high pressure", func(t *testing.T) {
ctx := wazevoapi.EnableHighRegisterPressure(context.Background())
spectest.RunCase(t, v1.Testcases, tc.name, ctx, config,
-1, 0, math.MaxInt)
})
})
}
}

View File

@@ -65,9 +65,9 @@ func (c compiledFunctionOffset) nativeBegin() int {
var _ wasm.Engine = (*engine)(nil)
// NewEngine returns the implementation of wasm.Engine.
func NewEngine(_ context.Context, _ api.CoreFeatures, _ filecache.Cache) wasm.Engine {
func NewEngine(ctx context.Context, _ api.CoreFeatures, _ filecache.Cache) wasm.Engine {
e := &engine{compiledModules: make(map[wasm.ModuleID]*compiledModule), refToBinaryOffset: make(map[ssa.FuncRef]int)}
e.compileBuiltinFunctions()
e.compileBuiltinFunctions(ctx)
return e
}
@@ -98,7 +98,7 @@ func (e *engine) compileModule(ctx context.Context, module *wasm.Module, listene
cm := &compiledModule{offsets: wazevoapi.NewModuleContextOffsetData(module)}
if module.IsHostModule {
return e.compileHostModule(module)
return e.compileHostModule(ctx, module)
}
importedFns, localFns := int(module.ImportFunctionCount), len(module.FunctionSection)
@@ -124,7 +124,7 @@ func (e *engine) compileModule(ctx context.Context, module *wasm.Module, listene
ssaBuilder := ssa.NewBuilder()
fe := frontend.NewFrontendCompiler(module, ssaBuilder, &cm.offsets)
machine := newMachine()
be := backend.NewCompiler(machine, ssaBuilder)
be := backend.NewCompiler(ctx, machine, ssaBuilder)
totalSize := 0 // Total binary size of the executable.
cm.functionOffsets = make([]compiledFunctionOffset, localFns)
@@ -136,6 +136,15 @@ func (e *engine) compileModule(ctx context.Context, module *wasm.Module, listene
fidx := wasm.Index(i + importedFns)
if wazevoapi.NeedFunctionNameInContext {
def := module.FunctionDefinition(fidx)
name := def.DebugName()
if len(def.ExportNames()) > 0 {
name = def.ExportNames()[0]
}
ctx = wazevoapi.SetCurrentFunctionName(ctx, fmt.Sprintf("[%d/%d] \"%s\"", i, len(module.CodeSection)-1, name))
}
_, needGoEntryPreamble := exportedFnIndex[fidx]
if sf := module.StartSection; sf != nil && *sf == fidx {
needGoEntryPreamble = true
@@ -169,8 +178,7 @@ func (e *engine) compileModule(ctx context.Context, module *wasm.Module, listene
bodies[i] = body
totalSize += len(body)
if wazevoapi.PrintMachineCodeHexPerFunction {
fmt.Printf("[[[machine code SSA for %d/%d %s]]]\n%s\n",
i, len(module.CodeSection)-1, exportedFnIndex[fidx], hex.EncodeToString(body))
fmt.Printf("[[[machine code for %s]]]\n%s\n\n", wazevoapi.GetCurrentFunctionName(ctx), hex.EncodeToString(body))
}
}
@@ -228,17 +236,10 @@ func (e *engine) compileLocalWasmFunction(
}
if wazevoapi.PrintSSA {
def := module.FunctionDefinition(functionIndex)
fmt.Printf("[[[SSA for %d/%d %s]]]%s\n", localFunctionIndex, len(module.CodeSection)-1, def.Debugname, ssaBuilder.Format())
fmt.Printf("[[[SSA for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), ssaBuilder.Format())
}
if wazevoapi.DeterministicCompilationVerifierEnabled {
def := module.FunctionDefinition(functionIndex)
name := def.DebugName()
if len(def.ExportNames()) > 0 {
name = def.ExportNames()[0]
}
ctx = wazevoapi.DeterministicCompilationVerifierSetCurrentFunctionName(ctx, fmt.Sprintf("[%d/%d]:\"%s\"", localFunctionIndex, len(module.CodeSection)-1, name))
wazevoapi.VerifyOrSetDeterministicCompilationContextValue(ctx, "SSA", ssaBuilder.Format())
}
@@ -246,8 +247,7 @@ func (e *engine) compileLocalWasmFunction(
ssaBuilder.RunPasses()
if wazevoapi.PrintOptimizedSSA {
def := module.FunctionDefinition(functionIndex)
fmt.Printf("[[[Optimized SSA for %d/%d %s]]]%s\n", localFunctionIndex, len(module.CodeSection)-1, def.Debugname, ssaBuilder.Format())
fmt.Printf("[[[Optimized SSA for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), ssaBuilder.Format())
}
if wazevoapi.DeterministicCompilationVerifierEnabled {
@@ -258,8 +258,7 @@ func (e *engine) compileLocalWasmFunction(
ssaBuilder.LayoutBlocks()
if wazevoapi.PrintBlockLaidOutSSA {
def := module.FunctionDefinition(functionIndex)
fmt.Printf("[[[Laidout SSA for %d/%d %s]]]%s\n", localFunctionIndex, len(module.CodeSection)-1, def.Debugname, ssaBuilder.Format())
fmt.Printf("[[[Laidout SSA for %s]]]%s\n", wazevoapi.GetCurrentFunctionName(ctx), ssaBuilder.Format())
}
if wazevoapi.DeterministicCompilationVerifierEnabled {
@@ -279,9 +278,9 @@ func (e *engine) compileLocalWasmFunction(
return copied, rels, goPreambleSize, nil
}
func (e *engine) compileHostModule(module *wasm.Module) (*compiledModule, error) {
func (e *engine) compileHostModule(ctx context.Context, module *wasm.Module) (*compiledModule, error) {
machine := newMachine()
be := backend.NewCompiler(machine, ssa.NewBuilder())
be := backend.NewCompiler(ctx, machine, ssa.NewBuilder())
num := len(module.CodeSection)
cm := &compiledModule{}
@@ -429,9 +428,9 @@ func (e *engine) NewModuleEngine(m *wasm.Module, mi *wasm.ModuleInstance) (wasm.
return me, nil
}
func (e *engine) compileBuiltinFunctions() {
func (e *engine) compileBuiltinFunctions(ctx context.Context) {
machine := newMachine()
be := backend.NewCompiler(machine, ssa.NewBuilder())
be := backend.NewCompiler(ctx, machine, ssa.NewBuilder())
e.builtinFunctions = &builtinFunctions{}
{

View File

@@ -96,11 +96,6 @@ func DeterministicCompilationVerifierGetRandomizedLocalFunctionIndex(ctx context
return ret
}
// DeterministicCompilationVerifierSetCurrentFunctionName sets the current function name to the given `functionName`.
func DeterministicCompilationVerifierSetCurrentFunctionName(ctx context.Context, functionName string) context.Context {
return context.WithValue(ctx, currentFunctionNameKey{}, functionName)
}
// VerifyOrSetDeterministicCompilationContextValue verifies that the `newValue` is the same as the previous value for the given `scope`
// and the current function name. If the previous value doesn't exist, it sets the value to the given `newValue`.
//
@@ -133,3 +128,38 @@ This is mostly due to (but might not be limited to):
os.Exit(1)
}
}
// nolint
const NeedFunctionNameInContext = PrintSSA ||
PrintOptimizedSSA ||
PrintBlockLaidOutSSA ||
PrintSSAToBackendIRLowering ||
PrintRegisterAllocated ||
PrintFinalizedMachineCode ||
PrintMachineCodeHexPerFunction ||
DeterministicCompilationVerifierEnabled
// SetCurrentFunctionName sets the current function name to the given `functionName`.
func SetCurrentFunctionName(ctx context.Context, functionName string) context.Context {
return context.WithValue(ctx, currentFunctionNameKey{}, functionName)
}
// GetCurrentFunctionName returns the current function name.
func GetCurrentFunctionName(ctx context.Context) string {
return ctx.Value(currentFunctionNameKey{}).(string)
}
// ----- High Register Pressure -----
type highRegisterPressureContextKey struct{}
// EnableHighRegisterPressure enables the high register pressure mode.
func EnableHighRegisterPressure(ctx context.Context) context.Context {
ctx = context.WithValue(ctx, highRegisterPressureContextKey{}, true)
return ctx
}
// IsHighRegisterPressure returns true if the current compilation is under high register pressure.
func IsHighRegisterPressure(ctx context.Context) bool {
return ctx.Value(highRegisterPressureContextKey{}) != nil
}