diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-06-09 23:12:46 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-06-09 23:12:46 +0200 |
commit | a00b6bdbfa72a1688a866edf5f825720c9874ada (patch) | |
tree | 82b2e1a62cc75c007039fe07663300706947f381 /sys/src/cmd/cc | |
parent | 5cdabc5eb16db432abcf61dc126bfb7f9b2978c1 (diff) |
8c, 6c: native ROL (cyclic shift) instruction support, improve peephole optimizers
introduce rolor() function to subsitute (a << c) | (a >> (bits(a) - c))
with (a <<< c) where <<< is cyclic rotation and c is constant.
this almost doubles the speed of chacha encryption of 386 and amd64.
the peephole optimizer used to stop when it hit a shift or rol
instruction when attempting to eleminate moves by register
substitution. but we do not have to as long as the shift count
operand is not CX (which cannot be substituted) and CX is not
a subject for substitution.
Diffstat (limited to 'sys/src/cmd/cc')
-rw-r--r-- | sys/src/cmd/cc/cc.h | 2 | ||||
-rw-r--r-- | sys/src/cmd/cc/sub.c | 41 |
2 files changed, 43 insertions, 0 deletions
diff --git a/sys/src/cmd/cc/cc.h b/sys/src/cmd/cc/cc.h index 01eb04562..dbaddffb5 100644 --- a/sys/src/cmd/cc/cc.h +++ b/sys/src/cmd/cc/cc.h @@ -273,6 +273,7 @@ enum OPROTO, OREGISTER, ORETURN, + OROL, OSET, OSIGN, OSIZE, @@ -694,6 +695,7 @@ int log2(uvlong); int vlog(Node*); int topbit(ulong); void simplifyshift(Node*); +void rolor(Node*); long typebitor(long, long); void diag(Node*, char*, ...); void warn(Node*, char*, ...); diff --git a/sys/src/cmd/cc/sub.c b/sys/src/cmd/cc/sub.c index ff1d6689d..91886cc35 100644 --- a/sys/src/cmd/cc/sub.c +++ b/sys/src/cmd/cc/sub.c @@ -903,6 +903,46 @@ if(debug['<'])prtree(n, "rewrite2"); n->left->op = o; } +/* + * replace shift/or with rotate left + */ +void +rolor(Node *n) +{ + Node *l, *r; + + if(!typeu[n->type->etype]) + return; + + l = n->left; + r = n->right; + switch(l->op){ + case OASHL: + if(r->op == OLSHR) + break; + return; + case OLSHR: + if(r->op == OASHL){ + r = l; + l = n->right; + break; + } + default: + return; + } + if(l->right->op != OCONST || r->right->op != OCONST) + return; + if(vconst(l->right) + vconst(r->right) != ewidth[n->type->etype]*8) + return; + if(l->left->type != n->type || r->left->type != n->type) + return; + if(l->left->op != ONAME || r->left->op != ONAME || l->left->sym != r->left->sym) + return; + + *n = *l; + n->op = OROL; +} + int side(Node *n) { @@ -1473,6 +1513,7 @@ Init onamesinit[] = OPROTO, 0, "PROTO", OREGISTER, 0, "REGISTER", ORETURN, 0, "RETURN", + OROL, 0, "ROL", OSET, 0, "SET", OSIGN, 0, "SIGN", OSIZE, 0, "SIZE", |