From a4f6a42d8f76a34b58d7b8d8963cb268c8962489 Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Tue, 5 Aug 2025 01:02:45 -0400 Subject: known-not-equivalent identities: a [+/-] lit[x, x =/= 0] --- ir.c | 14 ++++++++++++++ test.lang | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) 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) } -- cgit v1.2.3