mirror of
https://github.com/golang/go
synced 2024-11-19 15:05:00 -07:00
a0453a180f
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/55143 Reviewed-by: Keith Randall <khr@golang.org> |
||
---|---|---|
.. | ||
alias3.dir | ||
bench | ||
chan | ||
ddd2.dir | ||
dwarf | ||
fixedbugs | ||
import2.dir | ||
import4.dir | ||
interface | ||
intrinsic.dir | ||
ken | ||
linkname.dir | ||
method4.dir | ||
safe | ||
stress | ||
syntax | ||
uintptrescapes.dir | ||
64bit.go | ||
235.go | ||
alg.go | ||
alias1.go | ||
alias2.go | ||
alias3.go | ||
alias.go | ||
append1.go | ||
append.go | ||
args.go | ||
armimm.go | ||
assign1.go | ||
assign.go | ||
atomicload.go | ||
bigalg.go | ||
bigmap.go | ||
blank1.go | ||
blank.go | ||
bom.go | ||
bombad.go | ||
bounds.go | ||
chancap.go | ||
chanlinear.go | ||
char_lit1.go | ||
char_lit.go | ||
checkbce.go | ||
clearfat.go | ||
closedchan.go | ||
closure1.go | ||
closure2.go | ||
closure.go | ||
cmp6.go | ||
cmp.go | ||
cmplx.go | ||
cmplxdivide1.go | ||
cmplxdivide.c | ||
cmplxdivide.go | ||
complit1.go | ||
complit.go | ||
compos.go | ||
const1.go | ||
const2.go | ||
const3.go | ||
const4.go | ||
const5.go | ||
const6.go | ||
const.go | ||
convert1.go | ||
convert2.go | ||
convert3.go | ||
convert.go | ||
convlit1.go | ||
convlit.go | ||
convT2X.go | ||
copy1.go | ||
copy.go | ||
crlf.go | ||
ddd1.go | ||
ddd2.go | ||
ddd.go | ||
decl.go | ||
declbad.go | ||
defer.go | ||
deferfin.go | ||
deferprint.go | ||
deferprint.out | ||
devirt.go | ||
divide.go | ||
divmod.go | ||
empty.go | ||
env.go | ||
eof1.go | ||
eof.go | ||
errchk | ||
escape2.go | ||
escape2n.go | ||
escape3.go | ||
escape4.go | ||
escape5.go | ||
escape_array.go | ||
escape_because.go | ||
escape_calls.go | ||
escape_closure.go | ||
escape_field.go | ||
escape_iface.go | ||
escape_indir.go | ||
escape_level.go | ||
escape_map.go | ||
escape_param.go | ||
escape_slice.go | ||
escape_struct_param1.go | ||
escape_struct_param2.go | ||
escape_struct_return.go | ||
escape.go | ||
fibo.go | ||
finprofiled.go | ||
float_lit2.go | ||
float_lit3.go | ||
float_lit.go | ||
floatcmp.go | ||
for.go | ||
func1.go | ||
func2.go | ||
func3.go | ||
func4.go | ||
func5.go | ||
func6.go | ||
func7.go | ||
func8.go | ||
func.go | ||
funcdup2.go | ||
funcdup.go | ||
gc1.go | ||
gc2.go | ||
gc.go | ||
gcstring.go | ||
goprint.go | ||
goprint.out | ||
goto.go | ||
heapsampling.go | ||
helloworld.go | ||
helloworld.out | ||
if.go | ||
import1.go | ||
import2.go | ||
import4.go | ||
import5.go | ||
import6.go | ||
import.go | ||
index0.go | ||
index1.go | ||
index2.go | ||
index.go | ||
indirect1.go | ||
indirect.go | ||
init1.go | ||
init.go | ||
initcomma.go | ||
initialize.go | ||
initializerr.go | ||
initloop.go | ||
inline_caller.go | ||
inline_callers.go | ||
inline_literal.go | ||
inline_variadic.go | ||
inline.go | ||
int_lit.go | ||
intcvt.go | ||
intrinsic_atomic.go | ||
intrinsic.go | ||
iota.go | ||
label1.go | ||
label.go | ||
linkmain_run.go | ||
linkmain.go | ||
linkname.go | ||
linkobj.go | ||
linkx_run.go | ||
linkx.go | ||
literal.go | ||
live1.go | ||
live2.go | ||
live_syscall.go | ||
live.go | ||
locklinear.go | ||
loopbce.go | ||
makechan.go | ||
makenew.go | ||
mallocfin.go | ||
map1.go | ||
map.go | ||
maplinear.go | ||
mergemul.go | ||
method1.go | ||
method2.go | ||
method3.go | ||
method4.go | ||
method5.go | ||
method.go | ||
named1.go | ||
named.go | ||
nil.go | ||
nilcheck.go | ||
nilptr2.go | ||
nilptr3.go | ||
nilptr4.go | ||
nilptr.go | ||
nosplit.go | ||
notinheap2.go | ||
notinheap.go | ||
nowritebarrier.go | ||
nul1.go | ||
opt_branchlikely.go | ||
parentype.go | ||
peano.go | ||
phiopt.go | ||
print.go | ||
print.out | ||
printbig.go | ||
printbig.out | ||
prove.go | ||
range.go | ||
README.md | ||
recover1.go | ||
recover2.go | ||
recover3.go | ||
recover4.go | ||
recover5.go | ||
recover.go | ||
reflectmethod1.go | ||
reflectmethod2.go | ||
reflectmethod3.go | ||
reflectmethod4.go | ||
rename1.go | ||
rename.go | ||
reorder2.go | ||
reorder.go | ||
return.go | ||
rotate0.go | ||
rotate1.go | ||
rotate2.go | ||
rotate3.go | ||
rotate.go | ||
run.go | ||
rune.go | ||
runtime.go | ||
shift1.go | ||
shift2.go | ||
sieve.go | ||
sigchld.go | ||
sigchld.out | ||
simassign.go | ||
sinit_run.go | ||
sinit.go | ||
sizeof.go | ||
slice3.go | ||
slice3err.go | ||
slicecap.go | ||
sliceopt.go | ||
solitaire.go | ||
stack.go | ||
strength.go | ||
string_lit.go | ||
stringrange.go | ||
struct0.go | ||
switch2.go | ||
switch3.go | ||
switch4.go | ||
switch5.go | ||
switch6.go | ||
switch7.go | ||
switch.go | ||
tinyfin.go | ||
torture.go | ||
turing.go | ||
typecheck.go | ||
typecheckloop.go | ||
typeswitch1.go | ||
typeswitch2.go | ||
typeswitch3.go | ||
typeswitch.go | ||
uintptrescapes2.go | ||
uintptrescapes.go | ||
undef.go | ||
utf.go | ||
varerr.go | ||
varinit.go | ||
writebarrier.go | ||
zerodivide.go |
The test directory contains tests of the Go tool chain and runtime. It includes black box tests, regression tests, and error output tests. They are run as part of all.bash.
To run just these tests, execute:
go run run.go
Standard library tests should be written as regular Go tests in the appropriate package.
The tool chain and runtime also have regular Go tests in their packages. The main reasons to add a new test to this directory are:
- it is most naturally expressed using the test runner; or
- it is also applicable to
gccgo
and other Go tool chains.