ref: 9b44da35f3246fb6c0293a615a9bbb001f13840d
parent: e31d035cf358e05158c0de708f31f9050043d997
author: Ori Bernstein <[email protected]>
date: Tue Jan 7 19:32:02 EST 2014
Reduce redundant infers of expressions.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -918,6 +918,7 @@
Type *t;
Node *len;
+ *isconst = 1;
len = mkintlit(n->line, n->expr.nargs);
t = mktyarray(n->line, mktyvar(n->line), len);
for (i = 0; i < n->expr.nargs; i++) {
@@ -934,8 +935,10 @@
Type **types;
size_t i;
+ *isconst = 1;
types = xalloc(sizeof(Type *)*n->expr.nargs);
for (i = 0; i < n->expr.nargs; i++) {
+ infernode(st, n->expr.args[i], NULL, NULL);
n->expr.isconst = n->expr.isconst && n->expr.args[i]->expr.isconst;
types[i] = type(st, n->expr.args[i]);
}
@@ -951,8 +954,10 @@
uc = uconresolve(st, n);
t = tyfreshen(st, tf(st, uc->utype));
uc = tybase(t)->udecls[uc->id];
- if (uc->etype)
+ if (uc->etype) {
+ inferexpr(st, n->expr.args[1], NULL, NULL);
unify(st, n, uc->etype, type(st, n->expr.args[1]));
+ }
*isconst = n->expr.args[0]->expr.isconst;
settype(st, n, delayeducon(st, t));
}
@@ -1013,15 +1018,12 @@
}
}
-static void inferexpr(Inferstate *st, Node *n, Type *ret, int *sawret)
+static void infersub(Inferstate *st, Node *n, Type *ret, int *sawret, int *exprconst)
{
Node **args;
size_t i, nargs;
- Node *s;
- Type *t;
int isconst;
- assert(n->type == Nexpr);
args = n->expr.args;
nargs = n->expr.nargs;
isconst = 1;
@@ -1038,6 +1040,20 @@
}
if (ispureop[exprop(n)])
n->expr.isconst = isconst;
+ *exprconst = isconst;
+}
+
+static void inferexpr(Inferstate *st, Node *n, Type *ret, int *sawret)
+{
+ Node **args;
+ size_t i, nargs;
+ Node *s;
+ Type *t;
+ int isconst;
+
+ assert(n->type == Nexpr);
+ args = n->expr.args;
+ nargs = n->expr.nargs;
infernode(st, n->expr.idx, NULL, NULL);
switch (exprop(n)) {
/* all operands are same type */
@@ -1046,6 +1062,7 @@
case Omul: /* @a * @a -> @a */
case Odiv: /* @a / @a -> @a */
case Oneg: /* -@a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
t = type(st, args[0]);
constrain(st, n, type(st, args[0]), cstrtab[Tcnum]);
isconst = args[0]->expr.isconst;
@@ -1077,6 +1094,7 @@
case Obxoreq: /* @a ^= @a -> @a */
case Obsleq: /* @a <<= @a -> @a */
case Obsreq: /* @a >>= @a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
t = type(st, args[0]);
constrain(st, n, type(st, args[0]), cstrtab[Tcnum]);
constrain(st, n, type(st, args[0]), cstrtab[Tcint]);
@@ -1089,6 +1107,7 @@
settype(st, n, tf(st, t));
break;
case Oasn: /* @a = @a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
t = type(st, args[0]);
for (i = 1; i < nargs; i++)
t = unify(st, n, t, type(st, args[i]));
@@ -1107,6 +1126,7 @@
case Oge: /* @a >= @a -> bool */
case Olt: /* @a < @a -> bool */
case Ole: /* @a <= @b -> bool */
+ infersub(st, n, ret, sawret, &isconst);
t = type(st, args[0]);
for (i = 1; i < nargs; i++)
unify(st, n, t, type(st, args[i]));
@@ -1115,13 +1135,16 @@
/* reach into a type and pull out subtypes */
case Oaddr: /* &@a -> @a* */
+ infersub(st, n, ret, sawret, &isconst);
settype(st, n, mktyptr(n->line, type(st, args[0])));
break;
case Oderef: /* *@a* -> @a */
+ infersub(st, n, ret, sawret, &isconst);
t = unify(st, n, type(st, args[0]), mktyptr(n->line, mktyvar(n->line)));
settype(st, n, t->sub[0]);
break;
case Oidx: /* @a[@b::tcint] -> @a */
+ infersub(st, n, ret, sawret, &isconst);
t = mktyidxhack(n->line, mktyvar(n->line));
unify(st, n, type(st, args[0]), t);
constrain(st, n, type(st, args[1]), cstrtab[Tcint]);
@@ -1128,6 +1151,7 @@
settype(st, n, tf(st, t->sub[0]));
break;
case Oslice: /* @a[@b::tcint,@b::tcint] -> @a[,] */
+ infersub(st, n, ret, sawret, &isconst);
t = mktyidxhack(n->line, mktyvar(n->line));
unify(st, n, type(st, args[0]), t);
constrain(st, n, type(st, args[1]), cstrtab[Tcint]);
@@ -1137,19 +1161,24 @@
/* special cases */
case Omemb: /* @a.Ident -> @b, verify type(@a.Ident)==@b later */
+ infersub(st, n, ret, sawret, &isconst);
settype(st, n, mktyvar(n->line));
delayedcheck(st, n, curstab());
break;
case Osize: /* sizeof @a -> size */
+ infersub(st, n, ret, sawret, &isconst);
settype(st, n, mktylike(n->line, Tyuint));
break;
case Ocall: /* (@a, @b, @c, ... -> @r)(@a,@b,@c, ... -> @r) -> @r */
+ infersub(st, n, ret, sawret, &isconst);
unifycall(st, n);
break;
case Ocast: /* cast(@a, @b) -> @b */
+ infersub(st, n, ret, sawret, &isconst);
delayedcheck(st, n, curstab());
break;
case Oret: /* -> @a -> void */
+ infersub(st, n, ret, sawret, &isconst);
if (sawret)
*sawret = 1;
if (!ret)
@@ -1161,9 +1190,11 @@
settype(st, n, t);
break;
case Ojmp: /* goto void* -> void */
+ infersub(st, n, ret, sawret, &isconst);
settype(st, n, mktype(-1, Tyvoid));
break;
case Ovar: /* a:@a -> @a */
+ infersub(st, n, ret, sawret, &isconst);
/* if we created this from a namespaced var, the type should be
* set, and the normal lookup is expected to fail. Since we're
* already done with this node, we can just return. */
@@ -1187,6 +1218,7 @@
inferarray(st, n, &n->expr.isconst);
break;
case Olit: /* <lit>:@a::tyclass -> @a */
+ infersub(st, n, ret, sawret, &isconst);
switch (args[0]->lit.littype) {
case Lfunc:
infernode(st, args[0]->lit.fnval, NULL, NULL); break;
@@ -1199,6 +1231,7 @@
settype(st, n, type(st, args[0]));
break;
case Olbl: /* :lbl -> void* */
+ infersub(st, n, ret, sawret, &isconst);
settype(st, n, mktyptr(n->line, mktype(-1, Tyvoid)));
case Obad: case Ocjmp: case Oset:
case Oslbase: case Osllen: