aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-05-24 15:30:53 -0700
committerRuss Cox <rsc@golang.org>2010-05-24 15:30:53 -0700
commitd14baee96eaf3dcad4a35ed2855840074885ba13 (patch)
tree20ed584441d56812ebde2a3ee7afe537fa4f6bdf
parent426fef55858dd01ad9e9ecff647b4cd8699359bb (diff)
downloadgo-d14baee96eaf3dcad4a35ed2855840074885ba13.tar.gz
go-d14baee96eaf3dcad4a35ed2855840074885ba13.zip
6g: avoid unnecessary conversion in shift bounds check
R=ken2 CC=golang-dev https://golang.org/cl/1278042
-rw-r--r--src/cmd/6g/ggen.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index a92d945724..59a6d529dc 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -888,6 +888,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
int a, rcx;
Prog *p1;
uvlong sc;
+ Type *tcount;
a = optoas(op, nl->type);
@@ -920,8 +921,16 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
rcx = reg[D_CX];
nodreg(&n1, types[TUINT32], D_CX);
+
+ // Allow either uint32 or uint64 as shift type,
+ // to avoid unnecessary conversion from uint32 to uint64
+ // just to do the comparison.
+ tcount = types[simtype[nr->type->etype]];
+ if(tcount->etype < TUINT32)
+ tcount = types[TUINT32];
+
regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
- regalloc(&n3, types[TUINT64], &n1); // to clear high bits of CX
+ regalloc(&n3, tcount, &n1); // to clear high bits of CX
nodreg(&cx, types[TUINT64], D_CX);
memset(&oldcx, 0, sizeof oldcx);
@@ -929,6 +938,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
regalloc(&oldcx, types[TUINT64], N);
gmove(&cx, &oldcx);
}
+ cx.type = tcount;
if(samereg(&cx, res))
regalloc(&n2, nl->type, N);
@@ -946,9 +956,9 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
regfree(&n3);
// test and fix up large shifts
- nodconst(&n3, types[TUINT64], nl->type->width*8);
- gins(optoas(OCMP, types[TUINT64]), &n1, &n3);
- p1 = gbranch(optoas(OLT, types[TUINT64]), T);
+ nodconst(&n3, tcount, nl->type->width*8);
+ gins(optoas(OCMP, tcount), &n1, &n3);
+ p1 = gbranch(optoas(OLT, tcount), T);
if(op == ORSH && issigned[nl->type->etype]) {
nodconst(&n3, types[TUINT32], nl->type->width*8-1);
gins(a, &n3, &n2);
@@ -960,6 +970,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
gins(a, &n1, &n2);
if(oldcx.op != 0) {
+ cx.type = types[TUINT64];
gmove(&oldcx, &cx);
regfree(&oldcx);
}