New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: improve map iteration #18004

Open
cherrymui opened this Issue Nov 21, 2016 · 0 comments

Comments

Projects
None yet
4 participants
@cherrymui
Contributor

cherrymui commented Nov 21, 2016

Currently compiling this code

type T struct {
        a, b, c, d, e, f, g, h int
}

func f(m map[int]T) {
        for _, e := range m {
                g(e.f)
        }
}

//go:noinline
func g(int) {}

results

	0x0051 00081 (/tmp/x.go:8)	LEAQ	type.map[int]"".T(SB), AX
	0x0058 00088 (/tmp/x.go:8)	MOVQ	AX, (SP)
	0x005c 00092 (/tmp/x.go:8)	MOVQ	"".m+264(FP), AX
	0x0064 00100 (/tmp/x.go:8)	MOVQ	AX, 8(SP)
	0x0069 00105 (/tmp/x.go:8)	LEAQ	""..autotmp_1+152(SP), AX
	0x0071 00113 (/tmp/x.go:8)	MOVQ	AX, 16(SP)
	0x0076 00118 (/tmp/x.go:8)	PCDATA	$0, $1
	0x0076 00118 (/tmp/x.go:8)	CALL	runtime.mapiterinit(SB)
	0x007b 00123 (/tmp/x.go:8)	MOVQ	""..autotmp_1+152(SP), AX
	0x0083 00131 (/tmp/x.go:8)	TESTQ	AX, AX
	0x0086 00134 (/tmp/x.go:8)	JEQ	$0, 253
	0x0088 00136 (/tmp/x.go:8)	MOVQ	""..autotmp_1+160(SP), SI
	0x0090 00144 (/tmp/x.go:8)	TESTB	AL, (SI)
	0x0092 00146 (/tmp/x.go:8)	LEAQ	""..autotmp_2+88(SP), DI
	0x0097 00151 (/tmp/x.go:8)	DUFFCOPY	$840
	0x00aa 00170 (/tmp/x.go:8)	MOVQ	""..autotmp_1+152(SP), AX
	0x00b2 00178 (/tmp/x.go:8)	TESTB	AL, (AX)
	0x00b4 00180 (/tmp/x.go:8)	LEAQ	"".e+24(SP), DI
	0x00b9 00185 (/tmp/x.go:8)	LEAQ	""..autotmp_2+88(SP), SI
	0x00be 00190 (/tmp/x.go:8)	DUFFCOPY	$840
	0x00d1 00209 (/tmp/x.go:9)	MOVQ	"".e+64(SP), AX
	0x00d6 00214 (/tmp/x.go:9)	MOVQ	AX, (SP)
	0x00da 00218 (/tmp/x.go:9)	PCDATA	$0, $1
	0x00da 00218 (/tmp/x.go:9)	CALL	"".g(SB)
	0x00df 00223 (/tmp/x.go:8)	LEAQ	""..autotmp_1+152(SP), AX
	0x00e7 00231 (/tmp/x.go:8)	MOVQ	AX, (SP)
	0x00eb 00235 (/tmp/x.go:8)	PCDATA	$0, $1
	0x00eb 00235 (/tmp/x.go:8)	CALL	runtime.mapiternext(SB)
	0x00f0 00240 (/tmp/x.go:8)	MOVQ	""..autotmp_1+152(SP), AX
	0x00f8 00248 (/tmp/x.go:8)	TESTQ	AX, AX
	0x00fb 00251 (/tmp/x.go:8)	JNE	$0, 136

Note that there are two DUFFCOPYs. It first copies the data pointed by the pointer that mapiterinit/mapiternext returns to autotmp_2, then copies from autotmp_2 to e.

I think one copy should be enough.

It might be able to do zero copy in some circumstances (but sounds a little crazy for now). Maybe no function call before the variable die, no address-taken, read only?
(Currently, if T is SSA-able (i.e. smaller), it generates no copy.)

@cherrymui cherrymui added this to the Go1.9 milestone Nov 21, 2016

@randall77 randall77 modified the milestones: Go1.10, Go1.9 May 31, 2017

@bradfitz bradfitz modified the milestones: Go1.10, Go1.11 Nov 28, 2017

@bradfitz bradfitz modified the milestones: Go1.11, Unplanned May 18, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment