summaryrefslogtreecommitdiff
path: root/ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'ir.c')
-rw-r--r--ir.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/ir.c b/ir.c
index 6bd1313..4f360b5 100644
--- a/ir.c
+++ b/ir.c
@@ -261,6 +261,14 @@ static inline int node_op_associative(NodeType t) {
return 0;
}
+static inline int node_op_comparison(NodeType t) {
+ NodeType ops[] = { N_CMP_EQL, N_CMP_NEQ, N_CMP_LES, N_CMP_GTR, N_CMP_LTE, N_CMP_GTE };
+ for (unsigned i = 0; i < sizeof ops / sizeof *ops; i++) {
+ if (ops[i] == t) return 1;
+ }
+ return 0;
+}
+
/* when applied to the same input, at least one must be true */
static inline NodeType node_cmp_opposite(NodeType a) {
struct { NodeType l, r; } pairs[] = {
@@ -275,6 +283,16 @@ static inline NodeType node_cmp_opposite(NodeType a) {
return N_NONE;
}
+static inline NodeType node_cmp_flip_sign(NodeType a) {
+ switch (a) {
+ case N_CMP_LES: return N_CMP_GTR;
+ case N_CMP_LTE: return N_CMP_GTE;
+ case N_CMP_GTR: return N_CMP_LES;
+ case N_CMP_GTE: return N_CMP_LTE;
+ default: return a;
+ }
+}
+
/* when applied to the same input, at least one must be false */
static inline int node_cmp_incompat(NodeType a, NodeType b) {
struct { NodeType l, r; } pairs[] = {
@@ -661,6 +679,29 @@ zero_no_effect: if (node_eql_i64(CAR(n), 0)) return CDR(n);
break;
}
+ if (node_op_comparison(n->type)) {
+ if (T(CAR(n), N_OP_SHL) && T(CDR(n), N_OP_ADD) && node_eql_i64(CADR(n), 1)) {
+ if (node_equiv(CAAR(n), CDAR(n))) return NODE(n->type, CAAR(n), CDDR(n));
+ if (node_equiv(CAAR(n), CDDR(n))) return NODE(n->type, CAAR(n), CDAR(n));
+ }
+ if (T(CDR(n), N_OP_SHL) && T(CAR(n), N_OP_ADD) && node_eql_i64(CDDR(n), 1)) {
+ if (node_equiv(CDAR(n), CAAR(n))) return NODE(n->type, CDAR(n), CADR(n));
+ if (node_equiv(CDAR(n), CADR(n))) return NODE(n->type, CDAR(n), CAAR(n));
+ }
+ if (node_op_associative(CAR(n)->type) && T(CAR(n), CDR(n)->type)) {
+ if (node_equiv(CAAR(n), CDAR(n))) return NODE(n->type, CADR(n), CDDR(n));
+ if (node_equiv(CADR(n), CDAR(n))) return NODE(n->type, CAAR(n), CDDR(n));
+ if (node_equiv(CAAR(n), CDDR(n))) return NODE(n->type, CADR(n), CDAR(n));
+ if (node_equiv(CADR(n), CDDR(n))) return NODE(n->type, CAAR(n), CDAR(n));
+ }
+ if (T(CAR(n), N_OP_SUB) && T(CAR(n), N_OP_SUB) && node_equiv(CAAR(n), CDAR(n))) {
+ return NODE(node_cmp_flip_sign(n->type), CADR(n), CDDR(n));
+ }
+ if (T(CAR(n), N_OP_NEG) && T(CDR(n), N_OP_NEG)) {
+ return NODE(node_cmp_flip_sign(n->type), CAAR(n), CDAR(n));
+ }
+ }
+
return NULL;
}