diff options
| author | WormHeamer | 2025-08-04 04:26:12 -0400 |
|---|---|---|
| committer | WormHeamer | 2025-08-04 04:26:12 -0400 |
| commit | c97e987c3e0fd631cb694535859701248e1357bb (patch) | |
| tree | 3b34874691f48f5c421c8c2d01d98629499528ba | |
| parent | 7df7f08dca9c54ea93839300e7b4c78289baf640 (diff) | |
fix communative peepholes trampling type boundaries
| -rw-r--r-- | ir.c | 74 | ||||
| -rw-r--r-- | test.lang | 4 |
2 files changed, 49 insertions, 29 deletions
@@ -6,6 +6,24 @@ extern int no_opt; +/* convenience macros (lisp-inspired lol) */ + +#define CAR(n) n->in.data[0] +#define CDR(n) n->in.data[1] +#define CAAR(n) CAR(CAR(n)) +#define CADR(n) CDR(CAR(n)) +#define CDAR(n) CAR(CDR(n)) +#define CDDR(n) CDR(CDR(n)) +#define CAAAR(n) CAR(CAAR(n)) +#define CAADR(n) CDR(CAAR(n)) +#define CADAR(n) CAR(CADR(n)) +#define CADDR(n) CDR(CADR(n)) +#define CDAAR(n) CAR(CDAR(n)) +#define CDADR(n) CDR(CDAR(n)) +#define CDDAR(n) CAR(CDDR(n)) +#define CDDDR(n) CDR(CDDR(n)) +#define T(a,b) ((a)->type == b) + /* types */ int type_eql(Type *a, Type *b) { @@ -64,12 +82,13 @@ int type_check(Node *n) { case N_CMP_LES: case N_CMP_GTR: case N_CMP_LTE: case N_CMP_GTE: n->val.type = (Type) { .lvl = T_TOP, .t = T_BOOL }; - return n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT; + return CAR(n)->val.type.t == T_INT && CDR(n)->val.type.t == T_INT; case N_CMP_EQL: case N_CMP_NEQ: n->val.type = (Type) { .lvl = T_TOP, .t = T_BOOL }; - return (n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT) - || (n->in.data[0]->val.type.t == T_BOOL && n->in.data[1]->val.type.t == T_BOOL); + return type_base_eql(&n->in.data[0]->val.type, &n->in.data[1]->val.type); + /* (n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT) + || (n->in.data[0]->val.type.t == T_BOOL && n->in.data[1]->val.type.t == T_BOOL); */ default: return 1; } @@ -354,22 +373,6 @@ void node_peephole_in(Node *n, int idx, Proc *p, Lexer *l) { #define NODE(...) node_peephole(node_new(p, __VA_ARGS__), p, l) #define OP(...) NODE(n->type, __VA_ARGS__) -#define CAR(n) n->in.data[0] -#define CDR(n) n->in.data[1] -#define CAAR(n) CAR(CAR(n)) -#define CADR(n) CDR(CAR(n)) -#define CDAR(n) CAR(CDR(n)) -#define CDDR(n) CDR(CDR(n)) -#define CAAAR(n) CAR(CAAR(n)) -#define CAADR(n) CDR(CAAR(n)) -#define CADAR(n) CAR(CADR(n)) -#define CADDR(n) CDR(CADR(n)) -#define CDAAR(n) CAR(CDAR(n)) -#define CDADR(n) CDR(CDAR(n)) -#define CDDAR(n) CAR(CDDR(n)) -#define CDDDR(n) CDR(CDDR(n)) - -#define T(a,b) ((a)->type == b) static inline int node_eql_i64(Node *n, int64_t i) { return n->type == N_LIT && n->val.type.t == T_INT && n->val.i == i; @@ -411,6 +414,10 @@ static inline int node_equiv_input(Node *a, Node *b) { /* needs lexer for error reporting */ Node *node_idealize(Node *n, Proc *p, Lexer *l) { + if (!type_check(n)) { + type_err(n, l); + } + if (no_opt) return NULL; /* try to compute a literal value */ @@ -491,9 +498,19 @@ Node *node_idealize(Node *n, Proc *p, Lexer *l) { if (node_cmp_incompat(CAR(n)->type, CDR(n)->type) && node_equiv_input(CAR(n), CDR(n))) { return node_new_lit_bool(p, 0); } + if (CAR(n)->val.type.t == T_INT) { + if (T(CAR(n), N_OP_NOT) && node_equiv(CAAR(n), CDR(n))) return node_new_lit_i64(p, 0); + if (T(CDR(n), N_OP_NOT) && node_equiv(CDAR(n), CAR(n))) return node_new_lit_i64(p, 0); + } break; case N_OP_XOR: - if (same) return node_new_lit_i64(p, 0); + if (same) { + switch (CAR(n)->val.type.t) { + case T_INT: return node_new_lit_i64(p, 0); break; + case T_BOOL: return node_new_lit_bool(p, 0); break; + default: break; + } + } if (node_cmp_opposite(CAR(n)->type, CDR(n)->type) && node_equiv_input(CAR(n), CDR(n))) { return node_new_lit_bool(p, 1); } @@ -525,27 +542,33 @@ zero_no_effect: if (node_eql_i64(CAR(n), 0)) return CDR(n); /* transformations to help encourage constant folding */ /* the overall trend is to move them rightwards */ + /* need to check for type compatibility */ + #define C(a, b) type_eql(&(a)->val.type, &(b)->val.type) if (node_op_communative(n->type)) { /* op(lit, X) -> op(X, lit) */ if (T(CAR(n), N_LIT) && !T(CDR(n), N_LIT)) return OP(CDR(n), CAR(n)); /* op(X, op(Y,Z)) -> op(op(Y,Z), X) */ - if (!T(CAR(n), n->type) && T(CDR(n), n->type)) return OP(CDR(n), CAR(n)); + if (!T(CAR(n), n->type) && T(CDR(n), n->type) + && C(CAR(n), CDAR(n))) return OP(CDR(n), CAR(n)); /* op(op(X,Y), op(Z, lit)) -> op(op(X, op(Y, Z)), lit) */ - if (T(CAR(n), n->type) && T(CDR(n), n->type) && T(CDDR(n), N_LIT)) { + if (T(CAR(n), n->type) && T(CDR(n), n->type) && T(CDDR(n), N_LIT) + && C(CAAR(n), CDAR(n)) && C(CAR(n), CDR(n))) { return OP(OP(CAAR(n), OP(CADR(n), CDAR(n))), CDDR(n)); } /* op(op(X, lit), lit) -> op(X, op(lit, lit)) */ if (T(CDR(n), N_LIT) && T(CAR(n), n->type) - && !T(CAAR(n), N_LIT) && T(CADR(n), N_LIT)) { + && !T(CAAR(n), N_LIT) && T(CADR(n), N_LIT) + && C(CADR(n), CDR(n))) { return OP(CAAR(n), OP(CADR(n), CDR(n))); } /* op(op(X, lit), Y) -> op(op(X, Y), lit) */ if (T(CAR(n), n->type) && !T(CAAR(n), N_LIT) - && T(CADR(n), N_LIT) && !T(CDR(n), N_LIT)) { + && T(CADR(n), N_LIT) && !T(CDR(n), N_LIT) + && C(CADR(n), CDR(n))) { return OP(OP(CAAR(n), CDR(n)), CADR(n)); } } @@ -564,9 +587,6 @@ Node *node_peephole(Node *n, Proc *p, Lexer *l) { n = r; } /* FIXME: figure out why this shows the wrong position when in an assignment */ - if (!type_check(n)) { - type_err(n, l); - } return n; } @@ -9,6 +9,6 @@ // also single-line now proc main(a i64, b i64) { - let c = a + b - return (a - b) = (((a + b) - b) - b) + return (a = a) & (b = a) + // (true = 0) = (a xor b) } |
