From 6ab9f2fb0e3d7a6e6db182d5e4eec10c42bf5372 Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Tue, 5 Aug 2025 01:25:22 -0400 Subject: convert a + -lit -> a - lit; some add/sub inequivalence identities --- ir.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'ir.c') diff --git a/ir.c b/ir.c index d681d9c..7e7604b 100644 --- a/ir.c +++ b/ir.c @@ -372,8 +372,25 @@ static inline int u64_power_of_2(uint64_t x) { return tlz; } -/* will this become too slow eventually? */ -static inline int node_equiv(Node *a, Node *b) { +/* functions to query the compile-time equivalence of nodes */ +/* fairly conservative of necessity */ + +static int node_equiv(Node *a, Node *b); +static int node_known_neg_of(Node *a, Node *b) { + if (T(b, N_OP_NEG) && node_equiv(a, CAR(b))) return 1; + if (T(a, N_OP_NEG) && node_equiv(CAR(a), b)) return 1; + if (T(a, N_LIT) && T(b, N_LIT) && (a->val.type.t == b->val.type.t) && b->val.i == -a->val.i) return 1; + return 0; +} + +static inline int node_sub_add_equiv(Node *a, Node *b) { + if (node_equiv(CAR(a), CAR(b)) && !node_known_neg_of(CDR(a), CDR(b))) return 1; + if (node_equiv(CAR(a), CDR(b)) && !node_known_neg_of(CDR(a), CAR(b))) return 1; + return 0; +} + +static int node_equiv(Node *a, Node *b) { + /* will doing this recursively be too slow? */ if (a == b) return 1; if (a->type != b->type) return 0; if (a->in.len != b->in.len) return 0; @@ -384,10 +401,11 @@ 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; + if (T(a, N_OP_SUB) && T(b, N_OP_ADD) && node_sub_add_equiv(a, b)) return 1; return 0; } static inline int node_known_not_equiv(Node *a, Node *b) { @@ -516,6 +534,7 @@ Node *node_idealize(Node *n, Proc *p, Lexer *l) { if (CAR(n)->val.type.t == T_INT) { /* a + ~a = -1 */ if (T(CAR(n), N_OP_NOT) && node_equiv(CAAR(n), CDR(n))) return node_new_lit_i64(p, -1); + if (T(CDR(n), N_LIT) && CDR(n)->val.i < 0) return NODE(N_OP_SUB, CAR(n), node_new_lit_i64(p, -CDR(n)->val.i)); } if (T(CAR(n), N_OP_NEG)) return NODE(N_OP_SUB, CDR(n), CAAR(n)); if (T(CDR(n), N_OP_NEG)) return NODE(N_OP_SUB, CAR(n), CDAR(n)); -- cgit v1.2.3