The old code generated for a bounds check was
CMP
JLT ok
CALL panicindex
ok:
...
The new code is (once the linker finishes with it):
CMP
JGE panic
...
panic:
CALL panicindex
which moves the calls out of line, putting more useful
code in each cache line. This matters especially in tight
loops, such as in Fannkuch. The benefit is more modest
elsewhere, but real.
From test/bench/go1, amd64:
benchmark old ns/op new ns/op delta
BenchmarkBinaryTree17 6096092000 6088808000 -0.12%
BenchmarkFannkuch11 6151404000 4020463000 -34.64%
BenchmarkGobDecode 28990050 28894630 -0.33%
BenchmarkGobEncode 12406310 12136730 -2.17%
BenchmarkGzip 179923 179903 -0.01%
BenchmarkGunzip 11219 11130 -0.79%
BenchmarkJSONEncode 86429350 86515900 +0.10%
BenchmarkJSONDecode 334593800 315728400 -5.64%
BenchmarkRevcomp25M 1219763000 1180767000 -3.20%
BenchmarkTemplate 492947600 483646800 -1.89%
And 386:
benchmark old ns/op new ns/op delta
BenchmarkBinaryTree17 6354902000 6243000000 -1.76%
BenchmarkFannkuch11 8043769000 7326965000 -8.91%
BenchmarkGobDecode 19010800 18941230 -0.37%
BenchmarkGobEncode 14077500 13792460 -2.02%
BenchmarkGzip 194087 193619 -0.24%
BenchmarkGunzip 12495 12457 -0.30%
BenchmarkJSONEncode 125636400 125451400 -0.15%
BenchmarkJSONDecode 696648600 685032800 -1.67%
BenchmarkRevcomp25M 2058088000 2052545000 -0.27%
BenchmarkTemplate 602140000 589876800 -2.04%
To implement this, two new instruction forms:
JLT target // same as always
JLT $0, target // branch expected not taken
JLT $1, target // branch expected taken
The linker could also emit the prediction prefixes, but it
does not: expected taken branches are reversed so that the
expected case is not taken (as in example above), and
the default expectaton for such a jump is not taken
already.
R=golang-dev, gri, r, dave
CC=golang-dev
https://golang.org/cl/6248049
* Eliminate bounds check on known small shifts.
* Rewrite x<<s | x>>(32-s) as a rotate (constant s).
* More aggressive (but still minimal) range analysis.
R=ken, dave, iant
CC=golang-dev
https://golang.org/cl/6209077
This fixes issue 2444.
A big cleanup of all 31/32bit size boundaries i'll leave for another cl though. (see also issue 1700).
R=rsc
CC=golang-dev
https://golang.org/cl/5484058
To allow these types as map keys, we must fill in
equal and hash functions in their algorithm tables.
Structs or arrays that are "just memory", like [2]int,
can and do continue to use the AMEM algorithm.
Structs or arrays that contain special values like
strings or interface values use generated functions
for both equal and hash.
The runtime helper func runtime.equal(t, x, y) bool handles
the general equality case for x == y and calls out to
the equal implementation in the algorithm table.
For short values (<= 4 struct fields or array elements),
the sequence of elementwise comparisons is inlined
instead of calling runtime.equal.
R=ken, mpimenov
CC=golang-dev
https://golang.org/cl/5451105
Does as much as possible in data layout instead
of during the init function.
Handles var x = y; var y = z as a special case too,
because it is so prevalent in package unicode
(var Greek = _Greek; var _Greek = []...).
Introduces InitPlan description of initialized data
so that it can be traversed multiple times (for example,
in the copy handler).
Cuts package unicode's init function size by 8x.
All that remains there is map initialization, which
is on the chopping block too.
Fixes sinit.go test case.
Aggregate DATA instructions at end of object file.
Checkpoint. More to come.
R=ken2
CC=golang-dev
https://golang.org/cl/4969051
8g/cgen.c:
8g/gobj.c
. dropped unnecessary assignments;
8g/gg.h
. added varargckk pragmas;
8g/ggen.c
. dropped duplicate assignment;
8g/gsubr.c
. adjusted format in print statement;
. dropped unnecessary assignment;
. replaced GCC's _builtin_return_address(0) with Plan 9's
getcallerpc(&n) which is defined as a macro in <u.h>;
8g/list.c
. adjusted format in snprint statement;
8g/opt.h
. added varargck pragma (Adr*) that is specific for the invoking
modules;
8g/peep.c
. dropped unnecessary incrementation;
R=rsc
CC=golang-dev
https://golang.org/cl/4974044
#include "go.h" (or "gg.h")
becomes
#include <u.h>
#include <libc.h>
#include "go.h"
so that go.y can #include <stdio.h>
after <u.h> but before "go.h".
This is necessary on Plan 9.
R=ken2
CC=golang-dev
https://golang.org/cl/4971041
After allocparams and walk, remove unused auto variables
and re-layout the remaining in reverse alignment order.
R=rsc
CC=golang-dev
https://golang.org/cl/4568068
cannot allocate an audomatic temp
while real registers are allocated.
there is a chance that the automatic
will be allocated to one of the
allocated registers. the fix is to
not registerize such variables.
R=rsc
CC=golang-dev
https://golang.org/cl/1202042
* add runtime sliceslice1 for x[lo:]
* remove runtime arraytoslice, rewriting &arr into arr[0:len(arr)].
* port cgen_inline into 8g, 5g.
* use native memmove in maps
R=ken2
https://golang.org/cl/157106
likely to go back to registers for most temporaries.
most tests in lib pass. these fail:
datafmt
fmt
go/scanner
log
reflect
strconv
template
R=ken
OCL=29896
CL=29898
* floating point -> integer conversions.
x86 defines that overflow/underflow
results in 1<<15, 1<<31, 1<<63 for
int16, int32, int64. when building the
unsigned conversions out of the native signed
ones, 8g turns overflow/underflow into zero.
the spec does not say what should happen.
* many tiny bug fixes. can run a large number
of files from go/test now, and can fmt.Printf.
* struggling with byte register allocation
and float32 computation.
R=ken
OCL=29642
CL=29811
* string format changed
* files got renamed
* new files that i forgot to check in last time
updates are all copy and paste from 6g
R=ken
OCL=29385
CL=29400