commit c9538a1cb5279a7a70695c86ad31ea9f85436d59
parent 19e83e69aa412cea8f41a28506cc9bfcc84525c4
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Wed, 2 Sep 2015 14:57:54 +0200
Add more algebraic identities
Diffstat:
M | cc1/fold.c | | | 77 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- |
1 file changed, 61 insertions(+), 16 deletions(-)
diff --git a/cc1/fold.c b/cc1/fold.c
@@ -376,36 +376,81 @@ ones(int n)
return v;
}
+/*
+ * i || 0 => i,0
+ * i || 1 => i
+ * i && 0 => i,0
+ * i && 1 => i
+ * i >> 0 => i
+ * i << 0 => i
+ * i + 0 => i
+ * i - 0 => i
+ * i | 0 => i
+ * i ^ 0 => i
+ * i * 0 => i,0
+ * i * 1 => i
+ * i / 1 => i
+ * i & ~0 => i
+ * i % 1 => i,1
+ */
static Node *
-identity(int op, Node *lp, Node *rp)
+identity(int *op, Node *lp, Node *rp)
{
- int val;
+ int iszero, isone, istrue;
- switch (op) {
+ if (!rp)
+ return NULL;
+
+ iszero = cmpnode(rp, 0);
+ isone = cmpnode(rp, 1),
+ istrue = !iszero && rp->constant;
+
+ switch (*op) {
+ case OOR:
+ if (istrue)
+ goto change_to_comma;
+ if (iszero)
+ break;
+ return NULL;
+ case OAND:
+ if (iszero)
+ goto change_to_comma;
+ if (istrue)
+ break;
+ return NULL;
case OSHL:
case OSHR:
case OBXOR:
case OADD:
+ case OBOR:
case OSUB:
- val = 0;
- break;
- case ODIV:
- case OMOD:
+ if (iszero)
+ break;
+ return NULL;
case OMUL:
- case OBOR:
- val = 1;
- break;
+ if (iszero)
+ goto change_to_comma;
+ case ODIV:
+ if (isone)
+ break;
+ return NULL;
case OBAND:
- if (cmpnode(lp, ones(lp->type->size * 8)))
- goto free_right;
+ if (cmpnode(rp, ones(lp->type->size * 8)))
+ break;
+ return NULL;
+ case OMOD:
+ if (isone)
+ goto change_to_comma;
default:
return NULL;
}
- if (!cmpnode(rp, val))
- return NULL;
-free_right:
+
freetree(rp);
return lp;
+
+change_to_comma:
+ *op = OCOMMA;
+ return NULL;
}
Node *
@@ -416,7 +461,7 @@ simplify(int op, Type *tp, Node *lp, Node *rp)
commutative(&op, &lp, &rp);
if ((np = fold(op, tp, lp, rp)) != NULL)
return np;
- if ((np = identity(op, lp, rp)) != NULL)
+ if ((np = identity(&op, lp, rp)) != NULL)
return np;
return node(op, tp, lp, rp);
}