summaryrefslogtreecommitdiff
path: root/src/cmd/6g/ggen.c
diff options
context:
space:
mode:
authorKen Thompson <ken@golang.org>2009-08-06 22:33:12 -0700
committerKen Thompson <ken@golang.org>2009-08-06 22:33:12 -0700
commit1c9f132822f522ebf95a87fa3abb7f750223f83d (patch)
treea01e117d1d9aa4e3523dc7ee740388866e9542a6 /src/cmd/6g/ggen.c
parent158f050b444b2dd9cb1b30c4a609ad34b08bcc71 (diff)
downloadgolang-1c9f132822f522ebf95a87fa3abb7f750223f83d.tar.gz
divide by a constant power of 2
R=rsc OCL=32858 CL=32858
Diffstat (limited to 'src/cmd/6g/ggen.c')
-rw-r--r--src/cmd/6g/ggen.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index 64220bc84..4e71f75e5 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -533,8 +533,8 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
void
cgen_div(int op, Node *nl, Node *nr, Node *res)
{
- Node ax, dx, oldax, olddx, n1, n2;
- int rax, rdx;
+ Node ax, dx, oldax, olddx, n1, n2, n3;
+ int rax, rdx, n, w;
if(nl->ullman >= UINF) {
tempname(&n1, nl->type);
@@ -547,6 +547,86 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
nr = &n2;
}
+ if(nr->op != OLITERAL)
+ goto longdiv;
+
+ // special cases of mod/div
+ // by a constant
+ n = powtwo(nr);
+ w = nl->type->width*8;
+
+ if(n+1 >= w) {
+ // just sign bit
+ goto longdiv;
+ }
+
+ if(n < 0)
+ goto divbymul;
+
+ if(op == OMOD) {
+ // todo
+ goto longdiv;
+ }
+
+ switch(n) {
+ case 0:
+ // divide by 1
+ cgen(nl, res);
+ return;
+ case 1:
+ // divide by 2
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ if(issigned[nl->type->etype]) {
+ // develop -1 iff nl is negative
+ regalloc(&n2, nl->type, N);
+ gmove(&n1, &n2);
+ nodconst(&n3, nl->type, w-1);
+ gins(optoas(ORSH, nl->type), &n3, &n2);
+ gins(optoas(OSUB, nl->type), &n2, &n1);
+ regfree(&n2);
+ }
+ nodconst(&n2, nl->type, n);
+ gins(optoas(ORSH, nl->type), &n2, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ return;
+ default:
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ if(issigned[nl->type->etype]) {
+ // develop (2^k)-1 iff nl is negative
+ regalloc(&n2, nl->type, N);
+ gmove(&n1, &n2);
+ nodconst(&n3, nl->type, w-1);
+ gins(optoas(ORSH, nl->type), &n3, &n2);
+ nodconst(&n3, nl->type, w-n);
+ gins(optoas(ORSH, tounsigned(nl->type)), &n3, &n2);
+ gins(optoas(OADD, nl->type), &n2, &n1);
+ regfree(&n2);
+ }
+ nodconst(&n2, nl->type, n);
+ gins(optoas(ORSH, nl->type), &n2, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ }
+ return;
+
+divbymul:
+ switch(simtype[nl->type->etype]) {
+ default:
+ goto longdiv;
+
+ case TINT32:
+ case TUINT32:
+ case TINT64:
+ case TUINT64:
+ break;
+ }
+ // todo
+ goto longdiv;
+
+longdiv:
rax = reg[D_AX];
rdx = reg[D_DX];