mirror of
https://github.com/golang/go
synced 2024-11-22 06:14:39 -07:00
divide by a constant power of 2
R=rsc OCL=32858 CL=32858
This commit is contained in:
parent
2f9c48f6d1
commit
f1baf78247
@ -125,6 +125,8 @@ void sudoclean(void);
|
|||||||
int sudoaddable(int, Node*, Addr*);
|
int sudoaddable(int, Node*, Addr*);
|
||||||
void afunclit(Addr*);
|
void afunclit(Addr*);
|
||||||
void datagostring(Strlit*, Addr*);
|
void datagostring(Strlit*, Addr*);
|
||||||
|
int powtwo(Node*);
|
||||||
|
Type* tounsigned(Type*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* obj.c
|
* obj.c
|
||||||
|
@ -533,8 +533,8 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
|
|||||||
void
|
void
|
||||||
cgen_div(int op, Node *nl, Node *nr, Node *res)
|
cgen_div(int op, Node *nl, Node *nr, Node *res)
|
||||||
{
|
{
|
||||||
Node ax, dx, oldax, olddx, n1, n2;
|
Node ax, dx, oldax, olddx, n1, n2, n3;
|
||||||
int rax, rdx;
|
int rax, rdx, n, w;
|
||||||
|
|
||||||
if(nl->ullman >= UINF) {
|
if(nl->ullman >= UINF) {
|
||||||
tempname(&n1, nl->type);
|
tempname(&n1, nl->type);
|
||||||
@ -547,6 +547,86 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
|
|||||||
nr = &n2;
|
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];
|
rax = reg[D_AX];
|
||||||
rdx = reg[D_DX];
|
rdx = reg[D_DX];
|
||||||
|
|
||||||
|
@ -1861,3 +1861,55 @@ no:
|
|||||||
sudoclean();
|
sudoclean();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
powtwo(Node *n)
|
||||||
|
{
|
||||||
|
uvlong v, b;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(n == N || n->op != OLITERAL || n->type == T)
|
||||||
|
goto no;
|
||||||
|
if(!isint[n->type->etype])
|
||||||
|
goto no;
|
||||||
|
|
||||||
|
v = mpgetfix(n->val.u.xval);
|
||||||
|
b = 1ULL;
|
||||||
|
for(i=0; i<64; i++) {
|
||||||
|
if(b == v)
|
||||||
|
return i;
|
||||||
|
b = b<<1;
|
||||||
|
}
|
||||||
|
|
||||||
|
no:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type*
|
||||||
|
tounsigned(Type *t)
|
||||||
|
{
|
||||||
|
|
||||||
|
// this is types[et+1], but not sure
|
||||||
|
// that this relation is immutable
|
||||||
|
switch(t->etype) {
|
||||||
|
default:
|
||||||
|
print("tounsigned: unknown type %T\n", t);
|
||||||
|
break;
|
||||||
|
case TINT:
|
||||||
|
t = types[TUINT];
|
||||||
|
break;
|
||||||
|
case TINT8:
|
||||||
|
t = types[TUINT8];
|
||||||
|
break;
|
||||||
|
case TINT16:
|
||||||
|
t = types[TUINT16];
|
||||||
|
break;
|
||||||
|
case TINT32:
|
||||||
|
t = types[TUINT32];
|
||||||
|
break;
|
||||||
|
case TINT64:
|
||||||
|
t = types[TUINT64];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
45
test/ken/divconst.go
Normal file
45
test/ken/divconst.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "rand"
|
||||||
|
|
||||||
|
func test(a,b,c int64);
|
||||||
|
|
||||||
|
func
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
var a, b int64;
|
||||||
|
|
||||||
|
for i:=0; i<1e6; i++ {
|
||||||
|
a := rand.Int63() - 1<<62;
|
||||||
|
b = a/1; test(a,b,1);
|
||||||
|
b = a/2; test(a,b,2);
|
||||||
|
b = a/3; test(a,b,3);
|
||||||
|
b = a/4; test(a,b,4);
|
||||||
|
b = a/5; test(a,b,5);
|
||||||
|
b = a/6; test(a,b,6);
|
||||||
|
b = a/7; test(a,b,7);
|
||||||
|
b = a/8; test(a,b,8);
|
||||||
|
b = a/16; test(a,b,16);
|
||||||
|
b = a/32; test(a,b,32);
|
||||||
|
b = a/64; test(a,b,64);
|
||||||
|
b = a/128; test(a,b,128);
|
||||||
|
b = a/256; test(a,b,256);
|
||||||
|
b = a/16384; test(a,b,16384);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func
|
||||||
|
test(a,b,c int64)
|
||||||
|
{
|
||||||
|
d := a/c;
|
||||||
|
if d != b {
|
||||||
|
panicln(a, b, c, d);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user