summaryrefslogtreecommitdiff
path: root/ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'ir.c')
-rw-r--r--ir.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/ir.c b/ir.c
index f8c18f5..d681d9c 100644
--- a/ir.c
+++ b/ir.c
@@ -384,6 +384,16 @@ static inline int node_equiv(Node *a, Node *b) {
return 1;
}
+/* of necessity, this has to be pretty conservative */
+/* TODO: figure out a more thorough way of comparing node graphs */
+static inline int node_known_not_equiv_ord(Node *a, Node *b) {
+ if ((T(b, N_OP_ADD) || T(b, N_OP_SUB)) && node_equiv(a, CAR(b)) && !node_eql_i64(CDR(b), 0)) return 1;
+ return 0;
+}
+static inline int node_known_not_equiv(Node *a, Node *b) {
+ return node_known_not_equiv_ord(a, b) || node_known_not_equiv_ord(b, a);
+}
+
static inline int node_equiv_input(Node *a, Node *b) {
if (a->in.len != b->in.len) return 0;
for (int i = 0; i < a->in.len; i++) {
@@ -563,12 +573,16 @@ zero_no_effect: if (node_eql_i64(CAR(n), 0)) return CDR(n);
break;
case N_CMP_EQL:
if (same) return node_new_lit_bool(p, 1);
+ if (node_known_not_equiv(CAR(n), CDR(n))) return node_new_lit_bool(p, 0);
if (BOOL_EQ(CDR(n), 1)) return CAR(n);
if (BOOL_EQ(CDR(n), 0)) return NODE(N_OP_NOT, CAR(n));
if (T(CAR(n), N_OP_NOT) && node_equiv(CDR(n), CAAR(n))) return node_new_lit_bool(p, 0);
break;
case N_CMP_NEQ:
if (same) return node_new_lit_bool(p, 0);
+ if (node_known_not_equiv(CAR(n), CDR(n))) return node_new_lit_bool(p, 1);
+ if (BOOL_EQ(CDR(n), 0)) return CAR(n);
+ if (BOOL_EQ(CDR(n), 1)) return NODE(N_OP_NOT, CAR(n));
break;
case N_CMP_LES:
if (same) return node_new_lit_bool(p, 0);