summaryrefslogtreecommitdiff
path: root/ir.c
diff options
context:
space:
mode:
authorWormHeamer2025-08-05 01:25:22 -0400
committerWormHeamer2025-08-05 01:25:22 -0400
commit6ab9f2fb0e3d7a6e6db182d5e4eec10c42bf5372 (patch)
tree1753b0bc99e263b52f13f24434e53caddad16536 /ir.c
parenta4f6a42d8f76a34b58d7b8d8963cb268c8962489 (diff)
convert a + -lit -> a - lit; some add/sub inequivalence identities
Diffstat (limited to 'ir.c')
-rw-r--r--ir.c25
1 files changed, 22 insertions, 3 deletions
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));