Commit 31072e41 authored by Russ Cox's avatar Russ Cox

cmd/gc: replace x*8 by x<<3 etc

Fixes #4199.

R=ken2
CC=golang-dev
https://golang.org/cl/7322081
parent ac1015e7
......@@ -24,6 +24,7 @@ static Node* append(Node*, NodeList**);
static Node* sliceany(Node*, NodeList**);
static void walkcompare(Node**, NodeList**);
static void walkrotate(Node**);
static void walkmul(Node**, NodeList**);
static void walkdiv(Node**, NodeList**);
static int bounded(Node*, int64);
static Mpint mpzero;
......@@ -481,7 +482,6 @@ walkexpr(Node **np, NodeList **init)
case OAND:
case OSUB:
case OMUL:
case OHMUL:
case OLT:
case OLE:
......@@ -932,6 +932,12 @@ walkexpr(Node **np, NodeList **init)
walkexpr(&n->right, init);
goto ret;
case OMUL:
walkexpr(&n->left, init);
walkexpr(&n->right, init);
walkmul(&n, init);
goto ret;
case ODIV:
case OMOD:
walkexpr(&n->left, init);
......@@ -2897,6 +2903,70 @@ yes:
return;
}
/*
* walkmul rewrites integer multiplication by powers of two as shifts.
*/
static void
walkmul(Node **np, NodeList **init)
{
Node *n, *nl, *nr;
int pow, neg, w;
n = *np;
if(!isint[n->type->etype])
return;
if(n->right->op == OLITERAL) {
nl = n->left;
nr = n->right;
} else if(n->left->op == OLITERAL) {
nl = n->right;
nr = n->left;
} else
return;
neg = 0;
// x*0 is 0 (and side effects of x).
if(mpgetfix(nr->val.u.xval) == 0) {
cheapexpr(nl, init);
nodconst(n, n->type, 0);
goto ret;
}
// nr is a constant.
pow = powtwo(nr);
if(pow < 0)
return;
if(pow >= 1000) {
// negative power of 2, like -16
neg = 1;
pow -= 1000;
}
w = nl->type->width*8;
if(pow+1 >= w)// too big, shouldn't happen
return;
nl = cheapexpr(nl, init);
if(pow == 0) {
// x*1 is x
n = nl;
goto ret;
}
n = nod(OLSH, nl, nodintconst(pow));
ret:
if(neg)
n = nod(OMINUS, n, N);
typecheck(&n, Erv);
walkexpr(&n, init);
*np = n;
}
/*
* walkdiv rewrites division by a constant as less expensive
* operations.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment