1
0
mirror of https://github.com/golang/go synced 2024-10-04 16:31:22 -06:00
go/src/cmd/8g/gg.h
Russ Cox fefae6eed1 cmd/6g, cmd/8g: move panicindex calls out of line
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
2012-05-29 12:09:27 -04:00

181 lines
3.7 KiB
C

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef EXTERN
#define EXTERN extern
#endif
#include "../gc/go.h"
#include "../8l/8.out.h"
typedef struct Addr Addr;
struct Addr
{
int32 offset;
int32 offset2;
double dval;
Prog* branch;
char sval[NSNAME];
Sym* gotype;
Sym* sym;
Node* node;
int width;
uchar type;
uchar index;
uchar etype;
uchar scale; /* doubles as width in DATA op */
uchar pun; /* dont register variable */
};
#define A ((Addr*)0)
struct Prog
{
short as; // opcode
uint32 loc; // pc offset in this func
uint32 lineno; // source line that generated this
Addr from; // src address
Addr to; // dst address
Prog* link; // next instruction in this func
void* reg; // pointer to containing Reg struct
};
#define TEXTFLAG from.scale
// foptoas flags
enum
{
Frev = 1<<0,
Fpop = 1<<1,
Fpop2 = 1<<2,
};
EXTERN int32 dynloc;
EXTERN uchar reg[D_NONE];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
extern char* anames[];
EXTERN Prog zprog;
EXTERN Node* newproc;
EXTERN Node* deferproc;
EXTERN Node* deferreturn;
EXTERN Node* panicindex;
EXTERN Node* panicslice;
EXTERN Node* throwreturn;
EXTERN int maxstksize;
extern uint32 unmappedzero;
/*
* ggen.c
*/
void compile(Node*);
void proglist(void);
void gen(Node*);
Node* lookdot(Node*, Node*, int);
void cgen_as(Node*, Node*);
void cgen_callmeth(Node*, int);
void cgen_callinter(Node*, Node*, int);
void cgen_proc(Node*, int);
void cgen_callret(Node*, Node*);
void cgen_div(int, Node*, Node*, Node*);
void cgen_bmul(int, Node*, Node*, Node*);
void cgen_shift(int, int, Node*, Node*, Node*);
void cgen_dcl(Node*);
int needconvert(Type*, Type*);
void genconv(Type*, Type*);
void allocparams(void);
void checklabels();
void ginscall(Node*, int);
/*
* cgen.c
*/
void agen(Node*, Node*);
void agenr(Node *n, Node *a, Node *res);
void igen(Node*, Node*, Node*);
vlong fieldoffset(Type*, Node*);
void bgen(Node*, int, Prog*);
void sgen(Node*, Node*, int64);
void gmove(Node*, Node*);
Prog* gins(int, Node*, Node*);
int samaddr(Node*, Node*);
void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*);
int cgen_inline(Node*, Node*);
Node* ncon(uint32);
void mgen(Node*, Node*, Node*);
void mfree(Node*);
/*
* cgen64.c
*/
void cmp64(Node*, Node*, int, Prog*);
void cgen64(Node*, Node*);
/*
* gsubr.c
*/
void clearp(Prog*);
void proglist(void);
Prog* gbranch(int, Type*);
void expecttaken(Prog*, int);
Prog* prog(int);
void gaddoffset(Node*);
void gconv(int, int);
int conv2pt(Type*);
vlong convvtox(vlong, int);
void fnparam(Type*, int, int);
Prog* gop(int, Node*, Node*, Node*);
void setconst(Addr*, vlong);
void setaddr(Addr*, Node*);
int optoas(int, Type*);
int foptoas(int, Type*, int);
void ginit(void);
void gclean(void);
void regalloc(Node*, Type*, Node*);
void regfree(Node*);
Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int);
void nodconst(Node*, Type*, int64);
void gconreg(int, vlong, int);
void datagostring(Strlit*, Addr*);
void datastring(char*, int, Addr*);
void buildtxt(void);
Plist* newplist(void);
int isfat(Type*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*);
int dotaddable(Node*, Node*);
void afunclit(Addr*);
void split64(Node*, Node*, Node*);
void splitclean(void);
void nswap(Node*, Node*);
/*
* cplx.c
*/
int complexop(Node*, Node*);
void complexmove(Node*, Node*);
void complexgen(Node*, Node*);
void complexbool(int, Node*, Node*, int, Prog*);
/*
* list.c
*/
int Aconv(Fmt*);
int Dconv(Fmt*);
int Pconv(Fmt*);
int Rconv(Fmt*);
int Yconv(Fmt*);
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
#pragma varargck type "D" Addr*
#pragma varargck type "lD" Addr*