• Alberto Donizetti's avatar
    cmd/compile: combine x*n + y*n into (x+y)*n · a0453a18
    Alberto Donizetti authored
    There are a few cases where this can be useful. Apart from the obvious
    (and silly)
    
      100*n + 200*n
    
    where we generate one IMUL instead of two, consider:
    
      15*n + 31*n
    
    Currently, the compiler strength-reduces both imuls, generating:
    
        0x0000 00000	MOVQ	"".n+8(SP), AX
    	0x0005 00005 	MOVQ	AX, CX
    	0x0008 00008 	SHLQ	$4, AX
    	0x000c 00012 	SUBQ	CX, AX
    	0x000f 00015 	MOVQ	CX, DX
    	0x0012 00018 	SHLQ	$5, CX
    	0x0016 00022 	SUBQ	DX, CX
    	0x0019 00025 	ADDQ	CX, AX
    	0x001c 00028 	MOVQ	AX, "".~r1+16(SP)
    	0x0021 00033 	RET
    
    But combining the imuls is both faster and shorter:
    
    	0x0000 00000	MOVQ	"".n+8(SP), AX
    	0x0005 00005 	IMULQ	$46, AX
    	0x0009 00009	MOVQ	AX, "".~r1+16(SP)
    	0x000e 00014 	RET
    
    even without strength-reduction.
    
    Moreover, consider:
    
      5*n + 7*(n+1) + 11*(n+2)
    
    We already have a rule that rewrites 7(n+1) into 7n+7, so the
    generated code (without imuls merging) looks like this:
    
    	0x0000 00000 	MOVQ	"".n+8(SP), AX
    	0x0005 00005 	LEAQ	(AX)(AX*4), CX
    	0x0009 00009 	MOVQ	AX, DX
    	0x000c 00012 	NEGQ	AX
    	0x000f 00015 	LEAQ	(AX)(DX*8), AX
    	0x0013 00019 	ADDQ	CX, AX
    	0x0016 00022 	LEAQ	(DX)(CX*2), CX
    	0x001a 00026 	LEAQ	29(AX)(CX*1), AX
    	0x001f 00031 	MOVQ	AX, "".~r1+16(SP)
    
    But with imuls merging, the 5n, 7n and 11n factors get merged, and the
    generated code looks like this:
    
    	0x0000 00000 	MOVQ	"".n+8(SP), AX
    	0x0005 00005 	IMULQ	$23, AX
    	0x0009 00009 	ADDQ	$29, AX
    	0x000d 00013 	MOVQ	AX, "".~r1+16(SP)
    	0x0012 00018 	RET
    
    Which is both faster and shorter; that's also the exact same code that
    clang and the intel c compiler generate for the above expression.
    
    Change-Id: Ib4d5503f05d2f2efe31a1be14e2fe6cac33730a9
    Reviewed-on: https://go-review.googlesource.com/55143Reviewed-by: 's avatarKeith Randall <khr@golang.org>
    a0453a18
Name
Last commit
Last update
..
addr2line Loading commit data...
api Loading commit data...
asm Loading commit data...
cgo Loading commit data...
compile Loading commit data...
cover Loading commit data...
dist Loading commit data...
doc Loading commit data...
fix Loading commit data...
go Loading commit data...
gofmt Loading commit data...
internal Loading commit data...
link Loading commit data...
nm Loading commit data...
objdump Loading commit data...
pack Loading commit data...
pprof Loading commit data...
trace Loading commit data...
vendor Loading commit data...
vet Loading commit data...