Commit bb192d13 authored by Matthew Dempsky's avatar Matthew Dempsky Committed by Russ Cox

cmd/6c: Optimize rotate expressions to use rotate instructions.

For simplicity, only recognizes expressions of the exact form
"(x << a) | (x >> b)" where x is a variable and a and b are
integer constant expressions that add to x's bit width.

Fixes #4629.

$ cat rotate.c
unsigned int
rotate(unsigned int x)
{
        x = (x << 3) | (x >> (sizeof(x) * 8 - 3));
        return x;
}

## BEFORE
$ go tool 6c -S rotate.c
(rotate.c:2)	TEXT	rotate+0(SB),$0-8
(rotate.c:2)	MOVL	x+0(FP),!!DX
(rotate.c:4)	MOVL	DX,!!AX
(rotate.c:4)	SALL	$3,!!AX
(rotate.c:4)	MOVL	DX,!!CX
(rotate.c:4)	SHRL	$29,!!CX
(rotate.c:4)	ORL	CX,!!AX
(rotate.c:5)	RET	,!!
(rotate.c:5)	RET	,!!
(rotate.c:5)	END	,!!

## AFTER
$ go tool 6c -S rotate.c
(rotate.c:2)	TEXT	rotate+0(SB),$0-8
(rotate.c:4)	MOVL	x+0(FP),!!AX
(rotate.c:4)	ROLL	$3,!!AX
(rotate.c:5)	RET	,!!
(rotate.c:5)	RET	,!!
(rotate.c:5)	END	,!!

R=rsc, minux.ma
CC=golang-dev
https://golang.org/cl/7069056
parent 4730a226
......@@ -265,6 +265,18 @@ cgen(Node *n, Node *nn)
break;
}
}
if(n->op == OOR && l->op == OASHL && r->op == OLSHR
&& l->right->op == OCONST && r->right->op == OCONST
&& l->left->op == ONAME && r->left->op == ONAME
&& l->left->sym == r->left->sym
&& l->right->vconst + r->right->vconst == 8 * l->left->type->width) {
regalloc(&nod, l->left, nn);
cgen(l->left, &nod);
gopcode(OROTL, n->type, l->right, &nod);
gmove(&nod, nn);
regfree(&nod);
break;
}
if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
c = l->right->vconst;
......
......@@ -1360,6 +1360,16 @@ gopcode(int o, Type *ty, Node *f, Node *t)
a = ASALQ;
break;
case OROTL:
a = AROLL;
if(et == TCHAR || et == TUCHAR)
a = AROLB;
if(et == TSHORT || et == TUSHORT)
a = AROLW;
if(et == TVLONG || et == TUVLONG || et == TIND)
a = AROLQ;
break;
case OFUNC:
a = ACALL;
break;
......
......@@ -277,6 +277,18 @@ cgen(Node *n, Node *nn)
break;
}
}
if(n->op == OOR && l->op == OASHL && r->op == OLSHR
&& l->right->op == OCONST && r->right->op == OCONST
&& l->left->op == ONAME && r->left->op == ONAME
&& l->left->sym == r->left->sym
&& l->right->vconst + r->right->vconst == 8 * l->left->type->width) {
regalloc(&nod, l->left, nn);
cgen(l->left, &nod);
gopcode(OROTL, n->type, l->right, &nod);
gmove(&nod, nn);
regfree(&nod);
break;
}
if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
c = l->right->vconst;
......
......@@ -1253,6 +1253,14 @@ gopcode(int o, Type *ty, Node *f, Node *t)
a = ASALW;
break;
case OROTL:
a = AROLL;
if(et == TCHAR || et == TUCHAR)
a = AROLB;
if(et == TSHORT || et == TUSHORT)
a = AROLW;
break;
case OFUNC:
a = ACALL;
break;
......
......@@ -325,6 +325,7 @@ enum
OINDEX,
OFAS,
OREGPAIR,
OROTL,
OEND
};
......
......@@ -1515,6 +1515,7 @@ Init onamesinit[] =
OINDEX, 0, "INDEX",
OFAS, 0, "FAS",
OREGPAIR, 0, "REGPAIR",
OROTL, 0, "ROTL",
OEND, 0, "END",
-1, 0, 0,
};
......
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