From 0db36f94b6b099d9397f35677db34a14a06000c1 Mon Sep 17 00:00:00 2001 From: "alexander.nutz" Date: Mon, 27 May 2024 14:46:20 +0200 Subject: [PATCH] aaaaaaaaaaaaa --- ir/analysis.c | 8 +++++++- ir/builder.c | 14 ++++++++++++++ ir/dump.c | 2 +- ir/ir.c | 33 +++++++++++++++++++++++++++++++++ ir/ir.h | 9 ++++++++- ir/lifetimes.c | 12 ++++++++++++ ir/llir.h | 10 +++++++++- ir/transform/share_slots.c | 20 ++++++++++++++++++-- main.c | 6 ++++++ 9 files changed, 108 insertions(+), 6 deletions(-) diff --git a/ir/analysis.c b/ir/analysis.c index 29962ff..d43fe7d 100644 --- a/ir/analysis.c +++ b/ir/analysis.c @@ -169,10 +169,16 @@ bool vx_IrBlock_is_volatile(const vx_IrBlock *block) vx_IrType *vx_IrBlock_typeof_var(vx_IrBlock *block, vx_IrVar var) { vx_IrOp *decl = vx_IrBlock_root_get_var_decl(vx_IrBlock_root(block), var); + if (decl == NULL) + goto warn; + for (size_t i = 0; i < decl->outs_len; i ++) if (decl->outs[i].var == var) return decl->outs[i].type; - assert(false); + +warn: + fprintf(stderr, "VARIABLE %%%zu DECL ERROR (typeof_var)\n", var); + return NULL; } static size_t cost_lut[VX_IR_OP____END] = { diff --git a/ir/builder.c b/ir/builder.c index 270fb14..87bbb39 100644 --- a/ir/builder.c +++ b/ir/builder.c @@ -200,8 +200,22 @@ void vx_IrOp_add_param_s(vx_IrOp *op, vx_IrOp_add_param(op, vx_IrNamedValue_create(name, val)); } +void vx_IrOp_undeclare(vx_IrOp *op) +{ + vx_IrBlock *root = (vx_IrBlock*) vx_IrBlock_root(op->parent); + if (root) { + for (size_t i = 0; i < op->outs_len; i ++) { + vx_IrVar var = op->outs[i].var; + if (var < root->as_root.vars_len && vx_IrBlock_root_get_var_decl(root, var) == op) { + root->as_root.vars[var].decl_parent = NULL; + } + } + } +} + void vx_IrOp_destroy(vx_IrOp *op) { + // BEFORE CHANGING NOTE THAT MOST PASSES MISUSE THIS!!! vx_IrOp_remove_params(op); free(op->outs); free(op->states); diff --git a/ir/dump.c b/ir/dump.c index 765dee0..b74af45 100644 --- a/ir/dump.c +++ b/ir/dump.c @@ -165,7 +165,7 @@ void vx_IrOp_dump(const vx_IrOp *op, FILE *out, size_t indent) { if (j > 0) fputc(',', out); const vx_IrTypedVar var = op->outs[j]; - fprintf(out, "%s %%%zu", var.type->debugName, var.var); + fprintf(out, "%s %%%zu", var.type ? var.type->debugName : "NULLTYPE", var.var); } if (op->outs_len > 0) diff --git a/ir/ir.c b/ir/ir.c index f6bb3bc..0da4570 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -1,8 +1,41 @@ #include "ir.h" #include +#include #include + +void vx_IrBlock_llir_fix_decl(vx_IrBlock *root) { + assert(root->is_root); + + // TODO: WHY THE FUCK IS THIS EVEN REQUIRED???? + + memset(root->as_root.vars, 0, sizeof(*root->as_root.vars) * root->as_root.vars_len); + + size_t total = 0; + for (size_t i = 0; i < root->ops_len; i ++) { + vx_IrOp *op = &root->ops[i]; + + for (size_t j = 0; j < op->outs_len; j ++) { + vx_IrTypedVar out = op->outs[j]; + if (root->as_root.vars[out.var].decl_parent == NULL) { + vx_IrBlock_root_set_var_decl(root, out.var, op); + root->as_root.vars[out.var].ll_type = out.type; + total ++; + } + } + } +} + +void vx_IrOp_warn(vx_IrOp *op, const char *optMsg0, const char *optMsg1) { + vx_IrBlock *parent = op ? op->parent : NULL; + if (parent) { + fprintf(stderr, "WARN: in op idx %zu: %s %s\n", parent->ops - op, optMsg0 ? optMsg0 : "", optMsg1 ? optMsg1 : ""); + } else { + fprintf(stderr, "WARN: trying to warn() for non existant op!\n"); + } +} + // TODO: add boolean to stop traverse void vx_IrView_deep_traverse(vx_IrView top, void (*callback)(vx_IrOp *op, void *data), void *data) { for (size_t i = top.start; i < top.end; i ++) { diff --git a/ir/ir.h b/ir/ir.h index ef19226..3dfe64d 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -311,6 +311,8 @@ typedef enum { /** false for nop and label true for everything else */ bool vx_IrOpType_has_effect(vx_IrOpType type); +void vx_IrOp_undeclare(vx_IrOp *op); + #define SSAOPTYPE_LEN (VX_IR_OP____END - VX_IR_OP_NOP) extern const char *vx_IrOpType_names[SSAOPTYPE_LEN]; @@ -335,6 +337,8 @@ struct vx_IrOp_s { vx_IrOpType id; }; +void vx_IrOp_warn(vx_IrOp *op, const char *optMsg0, const char *optMsg1); + void vx_IrOp_dump(const vx_IrOp *op, FILE *out, size_t indent); typedef struct { @@ -409,7 +413,10 @@ static vx_IrOp *vx_IrBlock_root_get_var_decl(const vx_IrBlock *root, vx_IrVar va vx_IrBlock *parent = root->as_root.vars[var].decl_parent; if (parent == NULL) return NULL; - return parent->ops + root->as_root.vars[var].decl_idx; + size_t idx = root->as_root.vars[var].decl_idx; + if (idx >= parent->ops_len) + return NULL; + return parent->ops + idx; } struct IrStaticIncrement { diff --git a/ir/lifetimes.c b/ir/lifetimes.c index 0cbd710..e14cec4 100644 --- a/ir/lifetimes.c +++ b/ir/lifetimes.c @@ -7,6 +7,12 @@ void vx_IrBlock_lifetimes(vx_IrBlock *block) { assert(block->is_root); for (vx_IrVar var = 0; var < block->as_root.vars_len; var ++) { + vx_IrOp *decl = vx_IrBlock_root_get_var_decl(block, var); + if (decl == NULL) { + block->as_root.vars[var].ll_lifetime.first = NULL; + continue; + } + // llir shouldn't be nested vx_IrOp *start = (void*) -1; @@ -21,6 +27,12 @@ void vx_IrBlock_lifetimes(vx_IrBlock *block) { } } + if (start == (void*)-1) + start = decl; + + if (end == 0) + end = decl; + lifetime lt; lt.first = start; lt.last = end; diff --git a/ir/llir.h b/ir/llir.h index e655d1c..fb5e260 100644 --- a/ir/llir.h +++ b/ir/llir.h @@ -2,8 +2,16 @@ void vx_IrBlock_llir_lower(vx_IrBlock *block); -/** block needs to be 100% fat */ +void vx_IrBlock_llir_fix_decl(vx_IrBlock *root); + +/** block needs to be 100% flat */ void vx_IrBlock_lifetimes(vx_IrBlock *block); // block needs to be 100% flat, decl of vars must be known, decl won't be known after this fn anymore; adds type info to vars void vx_IrBlock_ll_share_slots(vx_IrBlock *block); + +static void llir_prep_lower(vx_IrBlock *block) { + vx_IrBlock_llir_fix_decl(block); + vx_IrBlock_lifetimes(block); + vx_IrBlock_ll_share_slots(block); +} diff --git a/ir/transform/share_slots.c b/ir/transform/share_slots.c index b80f97c..afbf2e5 100644 --- a/ir/transform/share_slots.c +++ b/ir/transform/share_slots.c @@ -6,8 +6,15 @@ // if start of lifetime A == end of lifetime B, we can still merge // block needs to be 100% flat, decl of vars must be known, decl won't be known after this fn anymore + +// TODO: figure out why it doesn't apply for overlapping*? lifetimes + void vx_IrBlock_ll_share_slots(vx_IrBlock *block) { for (vx_IrVar var = 0; var < block->as_root.vars_len; var ++) { + if (block->as_root.vars[var].decl_parent == NULL) + continue; + + // TODO: only search in lifetime: IrView of lifetime vx_IrView view = vx_IrView_of_all(block); bool get_rid = false; while (vx_IrView_find(&view, VX_IR_OP_PLACE)) { @@ -33,10 +40,11 @@ void vx_IrBlock_ll_share_slots(vx_IrBlock *block) { for (vx_IrVar var = 0; var < block->as_root.vars_len; var ++) { lifetime *lt = &block->as_root.vars[var].ll_lifetime; - vx_IrType *type = block->as_root.vars[var].ll_type; if (lt->first == NULL) continue; + + vx_IrType *type = block->as_root.vars[var].ll_type; for (vx_IrVar var2 = 0; var < block->as_root.vars_len; var ++) { if (var == var2) @@ -58,7 +66,15 @@ void vx_IrBlock_ll_share_slots(vx_IrBlock *block) { cmp_high = *lt; } - // TODO + if (cmp_low.last > cmp_high.first) + continue; + + // it's okay if end0 = start1 + + vx_IrView view = vx_IrView_of_all(block); + vx_IrView_rename_var(view, block, var, var2); + + break; } } } diff --git a/main.c b/main.c index f1bc097..fbcb4b9 100644 --- a/main.c +++ b/main.c @@ -119,12 +119,18 @@ static int cir_test(void) { printf("After LL IR opt:\n"); vx_IrBlock_dump(block, stdout, 0); + llir_prep_lower(block); + + printf("After LL IR lower prepare:\n"); + vx_IrBlock_dump(block, stdout, 0); + vx_IrBlock_destroy(block); return 0; } int main(void) { + // TODO: figure out why these break things vx_g_optconfig.loop_simplify = false; vx_g_optconfig.if_eval = false;