Skip to content

Commit

Permalink
codegen loops
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander.nutz committed Sep 20, 2024
1 parent 286b0c8 commit 2ec941a
Show file tree
Hide file tree
Showing 17 changed files with 395 additions and 55 deletions.
1 change: 1 addition & 0 deletions build.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct CompileData target_lib_files[] = {
SP(CT_C, "ir/transform/ssair_llir_lower.c"),
SP(CT_C, "ir/transform/cmov_expand.c"),
SP(CT_C, "ir/transform/ll_finalize.c"),
SP(CT_C, "ir/transform/lower_loops.c"),

DIR("build/common"),
SP(CT_C, "common/verify.c"),
Expand Down
3 changes: 2 additions & 1 deletion cg/x86_stupid/cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file)
{
Location* o = op->outs_len > 0 ? varData[op->outs[0].var].location : NULL;

size_t eaBytesWidth = o->bytesWidth;
size_t eaBytesWidth = o ? o->bytesWidth : 0;
switch (op->id)
{
case VX_IR_OP_LOAD_EA:
Expand Down Expand Up @@ -1498,6 +1498,7 @@ void vx_cg_x86stupid_gen(vx_IrBlock* block, FILE* out) {
vx_IrTypedVar var = block->ins[i];
assert(var.type->kind == VX_IR_TYPE_KIND_BASE);
size_t size = vx_IrType_size(var.type);
assert(size != 0);

if (var.type->base.isfloat) {
Location* loc;
Expand Down
14 changes: 14 additions & 0 deletions ir/analysis.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ size_t vx_IrOp_countSuccessors(vx_IrOp *op)
return count;
}

bool VX_IR_OPFILTER_ID__impl(vx_IrOp* op, void* idi) {
return op->id == (vx_IrOpType) (intptr_t) idi;
}

bool VX_IR_OPFILTER_COMPARISION__impl(vx_IrOp* op, void* ign0) {
(void) ign0;

Expand Down Expand Up @@ -138,6 +142,16 @@ bool vx_IrBlock_allMatch(vx_IrOp* first, vx_IrOp* last,
return true;
}

bool vx_IrBlock_noneMatch(vx_IrOp* first, vx_IrOp* last,
vx_IrOpFilter fil, void* data)
{
for (; first; first = first->next) {
if (fil(first, data)) return false;
if (first == last) break;
}
return true;
}

bool vx_IrBlock_nextOpListBetween(vx_IrBlock* block,
vx_IrOp** first, vx_IrOp** last,
vx_IrOpFilter matchBegin, void *data0,
Expand Down
1 change: 1 addition & 0 deletions ir/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ void vx_IrValue_dump(vx_IrValue value, FILE *out, const size_t indent) {

void vx_IrOp_dump(const vx_IrOp *op, FILE *out, size_t indent) {
assert(out);
assert(op);

for (size_t j = 0; j < indent; j ++)
fputs(" ", out);
Expand Down
3 changes: 1 addition & 2 deletions ir/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ bool vx_Irblock_alwaysIsVar(vx_IrBlock *block, vx_IrVar var, vx_IrValue v) {
}

void vx_Irblock_eval(vx_IrBlock *block, vx_IrValue *v) {
if (v->type == VX_IR_VAL_VAR)
while (vx_IrBlock_eval_var(block, v->var, v)) {}
while (v->type == VX_IR_VAL_VAR && vx_IrBlock_eval_var(block, v->var, v)) {}
}


Expand Down
14 changes: 11 additions & 3 deletions ir/ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ void vx_IrBlock_llir_fix_decl(vx_IrBlock *root) {
for (vx_IrOp *op = root->first; op; op = op->next) {
for (size_t j = 0; j < op->outs_len; j ++) {
vx_IrTypedVar out = op->outs[j];
if (vx_IrType_size(out.type) == 0) {
fprintf(stderr, "size of type %s in 0", out.type->debugName);
exit(1);
}
assert(out.var < root->as_root.vars_len);
vx_IrOp **decl = &root->as_root.vars[out.var].decl;
if (*decl == NULL) {
Expand Down Expand Up @@ -295,27 +299,31 @@ int vx_CU_compile(vx_CU * cu,
vx_CIrBlock_mksa_final(block);
vx_CIrBlock_fix(block); // TODO: why...

puts("post CIR lower:");
vx_IrBlock_dump(block, stdout, 0);

puts("post CIR lower:");
if (vx_ir_verify(block) != 0)
return 1;
});

FOR_BLOCK({
opt(block);

puts("post SSA IR opt:");
vx_IrBlock_dump(block, stdout, 0); // TODO remove

vx_IrBlock_flattenFlattenPleaseRec(block);

if (optionalOptimizedSsaIr != NULL)
vx_IrBlock_dump(block, optionalOptimizedSsaIr, 0);

puts("post SSA IR opt:");
if (vx_ir_verify(block) != 0)
return 1;
});

FOR_BLOCK({
vx_IrBlock_llir_preLower_loops(block);
vx_IrBlock_llir_lower(block);

vx_IrBlock_llir_fix_decl(block);
});

Expand Down
17 changes: 17 additions & 0 deletions ir/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,11 @@ vx_IrOp* vx_IrOp_nextWithEffect(vx_IrOp* op);

typedef bool (*vx_IrOpFilter)(vx_IrOp* op, void* userdata);

bool VX_IR_OPFILTER_ID__impl(vx_IrOp*,void*);
#define VX_IR_OPFILTER_ID(id) \
VX_IR_OPFILTER_ID__impl, \
(void*) (intptr_t) id

bool VX_IR_OPFILTER_COMPARISION__impl(vx_IrOp*,void*);
#define VX_IR_OPFILTER_COMPARISION \
VX_IR_OPFILTER_COMPARISION__impl, \
Expand Down Expand Up @@ -505,9 +510,21 @@ static vx_IrOp* vx_IrOp_nextWhile(vx_IrOp* op, vx_IrOpFilter match, void *data0)
return op;
}

static void vx_IrOp_earlierFirst(vx_IrOp** earlier, vx_IrOp** later)
{
if (vx_IrOp_after(*earlier, *later)) {
vx_IrOp* temp = *earlier;
*earlier = *later;
*later = temp;
}
}

bool vx_IrBlock_allMatch(vx_IrOp* first, vx_IrOp* last,
vx_IrOpFilter fil, void* data);

bool vx_IrBlock_noneMatch(vx_IrOp* first, vx_IrOp* last,
vx_IrOpFilter fil, void* data);

bool vx_IrOp_inRange(vx_IrOp* op,
vx_IrOp* first, vx_IrOp* last);

Expand Down
8 changes: 7 additions & 1 deletion ir/llir.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ir.h"
#include "opt.h"

#ifndef _LLIR_H
#define _LLIR_H
Expand All @@ -7,6 +8,8 @@ OPT_PASS void vx_opt_ll_binary(vx_IrBlock *block);

OPT_PASS void vx_opt_ll_tailcall(vx_IrBlock *block);

void vx_IrBlock_llir_preLower_loops(vx_IrBlock *block);

void vx_IrBlock_llir_lower(vx_IrBlock *block);

void vx_IrBlock_llir_fix_decl(vx_IrBlock *root);
Expand All @@ -26,10 +29,13 @@ void vx_IrBlock_ll_finalize(vx_IrBlock *block, bool needEpilog);

static void llir_prep_lower(vx_IrBlock *block) {
vx_IrBlock_llir_fix_decl(block);
//vx_IrBlock_llir_compact(block);
//vx_IrBlock_llir_compact(block); /TODO?
vx_IrBlock_lifetimes(block);
vx_IrBlock_ll_share_slots(block);
for (size_t i = 0; i < 2; i ++)
vx_opt_ll_inlineVars(block);
vx_opt_ll_binary(block);
vx_IrBlock_llir_fix_decl(block);
}

#endif //_LLIR_H
13 changes: 11 additions & 2 deletions ir/opt.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,18 @@ void opt(vx_IrBlock *block) {

void opt_ll(vx_IrBlock *block) {
vx_opt_ll_dce(block);
vx_opt_inline_vars(block);
for (size_t i = 0; i < vx_g_optconfig.consteval_iterations; i ++) {
vx_opt_ll_inlineVars(block);
vx_opt_vars(block);
}

vx_IrBlock_ll_cmov_expand(block); // this makes it non-ssa but ll_sched can handle it (but only because it's cmov!!!)
vx_opt_ll_sched(block);
vx_opt_vars(block);
vx_opt_ll_jumps(block);

vx_opt_ll_dce(block);
for (size_t i = 0; i < vx_g_optconfig.consteval_iterations; i ++) {
vx_opt_ll_inlineVars(block);
vx_opt_vars(block);
}
}
1 change: 1 addition & 0 deletions ir/opt.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ OPT_PASS void vx_opt_ll_jumps(vx_IrBlock *block);
OPT_PASS void vx_opt_simple_patterns(vx_IrBlock* block);
OPT_PASS void vx_opt_if_opts(vx_IrBlock* block);

OPT_PASS void vx_opt_ll_inlineVars(vx_IrBlock *block);
OPT_PASS void vx_opt_ll_dce(vx_IrBlock *block);
OPT_PASS void vx_opt_ll_condtailcall(vx_IrBlock *block);
OPT_PASS void vx_opt_ll_sched(vx_IrBlock *block);
Expand Down
26 changes: 26 additions & 0 deletions ir/opt/dce.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,33 @@ static void rmcode_before_label(vx_IrOp *op) {
}
}

static bool labelUsed(vx_IrBlock* block, size_t label)
{
for (vx_IrOp *op = block->first; op; op = op->next) {
if (op->id == VX_IR_OP_GOTO || op->id == VX_IR_OP_COND) {
size_t id = vx_IrOp_param(op, VX_IR_NAME_ID)->id;
if (id == label) return true;
}
}
return false;
}

void vx_opt_ll_dce(vx_IrBlock *block) {
for (vx_IrOp *op = block->first; op; op = op->next) {
if (op->id == VX_IR_OP_LABEL) {
size_t id = vx_IrOp_param(op, VX_IR_NAME_ID)->id;
if (!labelUsed(block, id)) {
vx_IrOp* pred = vx_IrOp_predecessor(op);
if (pred == NULL) {
block->first = op->next;
} else {
pred->next = op->next;
}
continue;
}
}
}

for (vx_IrOp *op = block->first; op; op = op->next)
if (vx_IrOp_endsFlow(op))
rmcode_before_label(op->next);
Expand Down
74 changes: 71 additions & 3 deletions ir/opt/inline_vars.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,24 @@ struct vx_IrView_substitute_var__data {
vx_IrBlock *block;
vx_IrVar old;
vx_IrValue new;
vx_IrOp* newSrc;
};

static bool vx_IrView_substitute_var__trav(vx_IrOp *op, void *dataIn) {
struct vx_IrView_substitute_var__data *data = dataIn;

vx_IrOp *first = op;
vx_IrOp *last = data->newSrc;
vx_IrOp_earlierFirst(&first, &last);

for (vx_IrOp* o = first->next; o; o = o->next) {
if (vx_IrOp_after(o, last)) break;

if (o->id == VX_IR_OP_LABEL) {
return false;
}
}

vx_IrBlock* block = op->parent;
for (size_t j = 0; j < block->outs_len; j ++) {
if (block->outs[j] == data->old) {
Expand All @@ -26,8 +39,8 @@ static bool vx_IrView_substitute_var__trav(vx_IrOp *op, void *dataIn) {
return false;
}

static void vx_IrBlock_substitute_var(vx_IrBlock *block, vx_IrVar old, vx_IrValue new) {
struct vx_IrView_substitute_var__data data = { .block = block, .old = old, .new = new };
static void vx_IrBlock_substitute_var(vx_IrBlock *block, vx_IrVar old, vx_IrValue new, vx_IrOp* newSrc) {
struct vx_IrView_substitute_var__data data = { .block = block, .old = old, .new = new, .newSrc = newSrc };
vx_IrBlock_deepTraverse(block, vx_IrView_substitute_var__trav, &data);
}

Expand All @@ -44,7 +57,7 @@ static bool trav (vx_IrOp *op, void *data)

for (size_t i = 0; i < op->outs_len; i ++) {
const vx_IrVar out = op->outs[i].var;
vx_IrBlock_substitute_var(block, out, value);
vx_IrBlock_substitute_var(block, out, value, op);
}

return false;
Expand All @@ -53,3 +66,58 @@ static bool trav (vx_IrOp *op, void *data)
void vx_opt_inline_vars(vx_IrBlock *block) {
vx_IrBlock_deepTraverse(block, trav, block);
}

void vx_opt_ll_inlineVars(vx_IrBlock *block)
{
for (vx_IrOp* imm = block->first; imm; imm = imm->next)
{
if (imm->id != VX_IR_OP_IMM)
continue;

vx_IrVar oVar = imm->outs[0].var;

vx_IrValue nVal = *vx_IrOp_param(imm, VX_IR_NAME_VALUE);

if (nVal.type == VX_IR_VAL_VAR) {
vx_IrVar nVar = nVal.var;
if (nVar == oVar) {
vx_IrOp* pred = vx_IrOp_predecessor(imm);
if (pred == NULL) {
block->first = imm->next;
} else {
pred->next = imm->next;
}
continue;
}
}

for (vx_IrOp* next = imm->next; next; next = next->next) {
if (next->id == VX_IR_OP_LABEL)
break;

FOR_INPUTS_REF(next, inpr, {
if (inpr->type == VX_IR_VAL_VAR && inpr->var == oVar) {
*inpr = nVal;
}
});


if (nVal.type == VX_IR_VAL_VAR) {
vx_IrVar nVar = nVal.var;
if (vx_IrOp_varInOuts(next, nVar))
break;
}

if (vx_IrOp_varInOuts(next, oVar))
break;

if (nVal.type == VX_IR_VAL_VAR) {
vx_IrVar nVar = nVal.var;
if (next->next == NULL) // we are at tail
for (size_t i = 0; i < block->outs_len; i ++)
if (block->outs[i] == oVar)
block->outs[i] = nVar;
}
}
}
}
Loading

0 comments on commit 2ec941a

Please sign in to comment.