• 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
..
archive Loading commit data...
bufio Loading commit data...
builtin Loading commit data...
bytes Loading commit data...
cmd Loading commit data...
compress Loading commit data...
container Loading commit data...
context Loading commit data...
crypto Loading commit data...
database/sql Loading commit data...
debug Loading commit data...
encoding Loading commit data...
errors Loading commit data...
expvar Loading commit data...
flag Loading commit data...
fmt Loading commit data...
go Loading commit data...
hash Loading commit data...
html Loading commit data...
image Loading commit data...
index/suffixarray Loading commit data...
internal Loading commit data...
io Loading commit data...
log Loading commit data...
math Loading commit data...
mime Loading commit data...
net Loading commit data...
os Loading commit data...
path Loading commit data...
plugin Loading commit data...
reflect Loading commit data...
regexp Loading commit data...
runtime Loading commit data...
sort Loading commit data...
strconv Loading commit data...
strings Loading commit data...
sync Loading commit data...
syscall Loading commit data...
testing Loading commit data...
text Loading commit data...
time Loading commit data...
unicode Loading commit data...
unsafe Loading commit data...
vendor/golang_org/x Loading commit data...
Make.dist Loading commit data...
all.bash Loading commit data...
all.bat Loading commit data...
all.rc Loading commit data...
androidtest.bash Loading commit data...
bootstrap.bash Loading commit data...
buildall.bash Loading commit data...
clean.bash Loading commit data...
clean.bat Loading commit data...
clean.rc Loading commit data...
cmp.bash Loading commit data...
iostest.bash Loading commit data...
make.bash Loading commit data...
make.bat Loading commit data...
make.rc Loading commit data...
naclmake.bash Loading commit data...
nacltest.bash Loading commit data...
race.bash Loading commit data...
race.bat Loading commit data...
run.bash Loading commit data...
run.bat Loading commit data...
run.rc Loading commit data...