summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-08-05 01:02:45 -0400
committerWormHeamer2025-08-05 01:02:45 -0400
commita4f6a42d8f76a34b58d7b8d8963cb268c8962489 (patch)
tree118041706259cb30ba1d10fff0a1286e5a1b1fac
parent0c9229c4147e0e3d4c065b36326e0e0b555f3441 (diff)
known-not-equivalent identities: a [+/-] lit[x, x =/= 0]
-rw-r--r--ir.c14
-rw-r--r--test.lang2
2 files changed, 15 insertions, 1 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);
diff --git a/test.lang b/test.lang
index 1d84f4b..1eee23a 100644
--- a/test.lang
+++ b/test.lang
@@ -11,5 +11,5 @@
proc main(a i64) {
let x = (a + -a) = (a xor a)
let y = (a + a) = (a * 2)
- return x & y & (a = a) & ((a + 2) <> a) & (a = ~a)
+ return (x & y & (a = a) & (a = ~a)) | ((a + 2) <> a)
}