Skip to content

cmd/compile: useless autotmp variables for slice literal #29547

@dsnet

Description

@dsnet

Using go1.11.2.

Consider the following snippet:

 var sink []V 

 func main() {
 	sink = []V{
-		(*tar.Reader)(nil),
+		VOf((*tar.Reader)(nil)),
 	}
 }

 type V = interface{}

 func VOf(t interface{}) V { return t }

The VOf function is a trivially useless function does nothing. If VOf function is missing, the main function is 176 bytes long, but if it is present, the function is 188 bytes long.

The assembly output without use of VOf is:

 "".main STEXT size=176 args=0x0 locals=0x18
 	(main.go:9)	TEXT	"".main(SB), $24-0
 	(main.go:9)	MOVQ	(TLS), CX
 	(main.go:9)	CMPQ	SP, 16(CX)
 	(main.go:9)	JLS	166
 	(main.go:9)	SUBQ	$24, SP
 	(main.go:9)	MOVQ	BP, 16(SP)
 	(main.go:9)	LEAQ	16(SP), BP
 	(main.go:9)	FUNCDATA	$0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
 	(main.go:9)	FUNCDATA	$1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
 	(main.go:9)	FUNCDATA	$3, gclocals·f6aec3988379d2bd21c69c093370a150(SB)
 	(main.go:10)	LEAQ	type.[1]interface {}(SB), AX
 	(main.go:10)	MOVQ	AX, (SP)
 	(main.go:10)	CALL	runtime.newobject(SB)
 	(main.go:10)	MOVQ	8(SP), AX
 	(main.go:11)	MOVQ	"".statictmp_0(SB), CX
 	(main.go:11)	LEAQ	type.*archive/tar.Reader(SB), DX
 	(main.go:11)	MOVQ	DX, (AX)
 	(main.go:11)	CMPL	runtime.writeBarrier(SB), $0
 	(main.go:11)	JNE	146
 	(main.go:11)	MOVQ	CX, 8(AX)
 	(main.go:10)	MOVQ	$1, "".sink+8(SB)
 	(main.go:10)	MOVQ	$1, "".sink+16(SB)
 	(main.go:10)	CMPL	runtime.writeBarrier(SB), $0
 	(main.go:10)	JNE	132
 	(main.go:10)	MOVQ	AX, "".sink(SB)
 	(main.go:13)	MOVQ	16(SP), BP
 	(main.go:13)	ADDQ	$24, SP
 	(main.go:13)	RET
 	(main.go:10)	LEAQ	"".sink(SB), DI
 	(main.go:10)	CALL	runtime.gcWriteBarrier(SB)
 	(main.go:10)	JMP	122
 	(main.go:11)	LEAQ	8(AX), DI
 	(main.go:10)	MOVQ	AX, DX
 	(main.go:11)	MOVQ	CX, AX
 	(main.go:11)	CALL	runtime.gcWriteBarrier(SB)
 	(main.go:10)	MOVQ	DX, AX
 	(main.go:11)	JMP	84
 	(main.go:11)	NOP
 	(main.go:9)	CALL	runtime.morestack_noctxt(SB)
 	(main.go:9)	JMP	0

However, calling VOf results in the generation of an autotmp variables.

 "".main STEXT size=188 args=0x0 locals=0x20
 	(main.go:9)	TEXT	"".main(SB), $32-0
 	(main.go:9)	MOVQ	(TLS), CX
 	(main.go:9)	CMPQ	SP, 16(CX)
 	(main.go:9)	JLS	178
 	(main.go:9)	SUBQ	$32, SP
 	(main.go:9)	MOVQ	BP, 24(SP)
 	(main.go:9)	LEAQ	24(SP), BP
 	(main.go:9)	FUNCDATA	$0, gclocals·69c1753bd5f81501d95132d08af04464(SB)
 	(main.go:9)	FUNCDATA	$1, gclocals·9fb7f0986f647f17cb53dda1484e0f7a(SB)
 	(main.go:9)	FUNCDATA	$3, gclocals·ba192201ac73f95fb90b551d9176d705(SB)
 	(main.go:11)	MOVQ	"".statictmp_0(SB), AX
+	(main.go:11)	MOVQ	AX, ""..autotmp_9+16(SP)
 	(main.go:10)	LEAQ	type.[1]interface {}(SB), CX
 	(main.go:10)	MOVQ	CX, (SP)
 	(main.go:10)	CALL	runtime.newobject(SB)
 	(main.go:10)	MOVQ	8(SP), AX
 	(main.go:10)	LEAQ	type.*archive/tar.Reader(SB), CX
 	(main.go:10)	MOVQ	CX, (AX)
 	(main.go:10)	CMPL	runtime.writeBarrier(SB), $0
 	(main.go:10)	JNE	156
+	(main.go:10)	MOVQ	""..autotmp_9+16(SP), CX
 	(main.go:10)	MOVQ	CX, 8(AX)
 	(main.go:10)	MOVQ	$1, "".sink+8(SB)
 	(main.go:10)	MOVQ	$1, "".sink+16(SB)
 	(main.go:10)	CMPL	runtime.writeBarrier(SB), $0
 	(main.go:10)	JNE	142
 	(main.go:10)	MOVQ	AX, "".sink(SB)
 	(main.go:13)	MOVQ	24(SP), BP
 	(main.go:13)	ADDQ	$32, SP
 	(main.go:13)	RET
 	(main.go:10)	LEAQ	"".sink(SB), DI
 	(main.go:10)	CALL	runtime.gcWriteBarrier(SB)
 	(main.go:10)	JMP	132
 	(main.go:10)	LEAQ	8(AX), DI
 	(main.go:10)	MOVQ	AX, CX
+	(main.go:10)	MOVQ	""..autotmp_9+16(SP), AX
 	(main.go:10)	CALL	runtime.gcWriteBarrier(SB)
 	(main.go:10)	MOVQ	CX, AX
 	(main.go:10)	JMP	94
 	(main.go:10)	NOP
 	(main.go:9)	CALL	runtime.morestack_noctxt(SB)
 	(main.go:9)	JMP	0

An additional autotmp variable is added for every element in the slice, so large slice literals are noticeably more bloated with VOf than without.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions