summaryrefslogtreecommitdiff
path: root/6
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2014-09-09 00:37:08 -0400
committerOri Bernstein <ori@eigenstate.org>2015-08-23 15:31:15 -0700
commit6a921aa5b2045b172370c1677c1e3f75b8c3cfc4 (patch)
tree97482bd5b2e150c4d89d8dcafecf4c7627a4582e /6
parentf90519332a6d24444a54c2b0943f705e8579550f (diff)
downloadmc-6a921aa5b2045b172370c1677c1e3f75b8c3cfc4.tar.gz
Generates 'rol' instructions.
This doesn't seem to have the performance effect I was hoping for with the sha1 calculaton, but it still improves code gen time, since there are fewer dumb, wasteful instructions.
Diffstat (limited to '6')
-rw-r--r--6/insns.def11
-rw-r--r--6/isel.c60
2 files changed, 70 insertions, 1 deletions
diff --git a/6/insns.def b/6/insns.def
index 8682263..4838061 100644
--- a/6/insns.def
+++ b/6/insns.def
@@ -92,6 +92,7 @@ Insn(Iimul,
"\tIMUL%T %X,%R\n",
Use(.l={1,2}),
Def(.l={2}))
+
/* there is no imul for 8 bit values. */
Insn(Iimul_r,
"\timul%t %r\n",
@@ -168,6 +169,16 @@ Insn(Ishr,
"\tSHR%2T %U,%R\n",
Use(.l={1,2}),
Def(.l={2}))
+Insn(Irol,
+ "\trol%2t %u,%r\n",
+ "\tROL%2T %U,%R\n",
+ Use(.l={1,2}),
+ Def(.l={2}))
+Insn(Iror,
+ "\tror%2t %u,%r\n",
+ "\tROR%2T %U,%R\n",
+ Use(.l={1,2}),
+ Def(.l={2}))
Insn(Itest,
"\ttest%t %x,%r\n",
diff --git a/6/isel.c b/6/isel.c
index 6cc8ab2..4a0295e 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -593,6 +593,59 @@ static Loc *gencall(Isel *s, Node *n)
return ret;
}
+static int litval(Node *n, vlong *v)
+{
+ Node *l;
+
+ if (exprop(n) != Olit)
+ return 0;
+ l = n->expr.args[0];
+ if (l->lit.littype != Lint)
+ return 0;
+ *v = l->lit.intval;
+ return 1;
+}
+
+int isrol(Isel *s, Node *l, Node *r, Loc **dist, Loc **rol)
+{
+ vlong a, b, sz;
+
+ sz = size(r)*8;
+ /* check if we have paired left/right shifts */
+ if (exprop(l) != Obsl && exprop(l) != Obsr)
+ return 0;
+ if (exprop(r) != Obsl && exprop(r) != Obsr)
+ return 0;
+ if (exprop(r) == exprop(l))
+ return 0;
+
+ /* check if we're shifting by constants */
+ if (!litval(l->expr.args[1], &a))
+ return 0;
+ if (!litval(r->expr.args[1], &b))
+ return 0;
+
+ /* and we're shifting the same variable */
+ if (exprop(l->expr.args[0]) != Ovar)
+ return 0;
+ if (exprop(r->expr.args[0]) != Ovar)
+ return 0;
+ if (l->expr.args[0]->expr.did != r->expr.args[0]->expr.did)
+ return 0;
+
+ /* and then figure out the shift amount */
+ if (a + b != sz)
+ return 0;
+ if (exprop(l) == Obsl)
+ *dist = loclit(a, mode(l));
+ else
+ *dist = loclit(sz - a, mode(l));
+ *rol = selexpr(s, l->expr.args[0]);
+ return 1;
+}
+
+
+
Loc *selexpr(Isel *s, Node *n)
{
Loc *a, *b, *c, *d, *r;
@@ -608,9 +661,14 @@ Loc *selexpr(Isel *s, Node *n)
switch (exprop(n)) {
case Oadd: r = binop(s, Iadd, args[0], args[1]); break;
case Osub: r = binop(s, Isub, args[0], args[1]); break;
- case Obor: r = binop(s, Ior, args[0], args[1]); break;
case Oband: r = binop(s, Iand, args[0], args[1]); break;
case Obxor: r = binop(s, Ixor, args[0], args[1]); break;
+ case Obor:
+ if (isrol(s, args[0], args[1], &d, &r))
+ g(s, Irol, d, r, NULL);
+ else
+ r = binop(s, Ior, args[0], args[1]);
+ break;
case Omul:
if (size(args[0]) == 1) {
a = selexpr(s, args[0]);