Skip to content

cmd/compile: prefer to cheaply re-materialize after call site instead of spilling #32255

Open
@martisch

Description

@martisch

go tip

While working on changing runtime.growslice to not return the length of the new slice (like was done for runtime.makeslice 020a18c) I ran into the issue of not being able to make the compiler rematerialize the new slice length instead of spilling it in

func (s *state) append(n *Node, inplace bool) *ssa.Value {

There generally seems to be a missed opportunity for the compiler to prefer recomputing a value that is cheap to compute from other values that too need to be loaded after a call.

Hand distilled example:

//go:noinline
func spilltest(s []int, a int) (int, int) {
	b := a + 1
	if b > len(s) {
		somecall()
	}
	return a, b
}

produces:

  0x450380	MOVQ FS:0xfffffff8, CX			
  0x450389	CMPQ 0x10(CX), SP			
  0x45038d	JBE 0x4503d8				
  0x45038f	SUBQ $0x10, SP				
  0x450393	MOVQ BP, 0x8(SP)			
  0x450398	LEAQ 0x8(SP), BP			
  0x45039d	MOVQ 0x30(SP), AX			
  0x4503a2	LEAQ 0x1(AX), CX // first computation of b			
  0x4503a6	MOVQ 0x20(SP), DX			
  0x4503ab	CMPQ DX, CX				
  0x4503ae	JG 0x4503c4				
  0x4503b0	MOVQ AX, 0x38(SP)			
  0x4503b5	MOVQ CX, 0x40(SP)		
  0x4503ba	MOVQ 0x8(SP), BP			
  0x4503bf	ADDQ $0x10, SP				
  0x4503c3	RET					
  0x4503c4	MOVQ CX, 0(SP) // Avoid this spill					
  0x4503c8	CALL main.somecall(SB)			
  0x4503cd	MOVQ 0x30(SP), AX			
  0x4503d2	MOVQ 0(SP), CX // do LEAQ 0x1(AX), CX here instead to compute b
  0x4503d6	JMP 0x4503b0				
  0x4503d8	CALL runtime.morestack_noctxt(SB)	
  0x4503dd	JMP main.spilltest(SB)			

Neither

func spilltest(s []int, a int) (int, int) {
	b := a + 1
	if b > len(s) {
		somecall()
		b = a + 1
	}
	return a, b
}

Or

func spilltest(s []int, a int) (int, int) {
	b := a + 1
	if b > len(s) {
		somecall()
	}
        c := a + 1
	return a, c
}

avoids the spilling.

@josharian @randall77 @cherrymui

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performancecompiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions