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
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;
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;
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;
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;
OINDEX,
OFAS,
OREGPAIR,
+ OROTL,
OEND
};
OINDEX, 0, "INDEX",
OFAS, 0, "FAS",
OREGPAIR, 0, "REGPAIR",
+ OROTL, 0, "ROTL",
OEND, 0, "END",
-1, 0, 0,
};