From 2f92dedb4c00bc2c107b91433f8e5c7284d77967 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Fri, 4 May 2012 10:01:38 +0200 Subject: [PATCH 1/7] Move the output block of a loop to after the loop, otherwise IR dumps looks just messy... note that this is merely a cosmetic change --- ast.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ast.c b/ast.c index c965947..e796215 100644 --- a/ast.c +++ b/ast.c @@ -939,6 +939,9 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value ir_block *bincrement, *end_bincrement; ir_block *bout, *bin; + /* let's at least move the outgoing block to the end */ + size_t bout_id; + /* 'break' and 'continue' need to be able to find the right blocks */ ir_block *bcontinue = NULL; ir_block *bbreak = NULL; @@ -1014,6 +1017,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value bpostcond = end_bpostcond = NULL; } + bout_id = func->ir_func->blocks_count; bout = ir_function_create_block(func->ir_func, ast_function_label(func, "after_loop")); if (!bout) return false; @@ -1135,5 +1139,13 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value return false; } + /* Move 'bout' to the end */ + if (!ir_function_blocks_remove(func->ir_func, bout_id) || + !ir_function_blocks_add(func->ir_func, bout)) + { + ir_block_delete(bout); + return false; + } + return true; } From e0331ef15f0f8351fb3781f9cf5e74f4efd37b32 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Fri, 4 May 2012 10:20:04 +0200 Subject: [PATCH 2/7] Changing life-range calculation to include the last read because then it doesn't need another vector to keep elements in. In order for this to make sense, the life-range overlap test now returns false if the end of one range _equals_ the beginning of the other, since that's not truly overlapping anymore --- ir.c | 51 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/ir.c b/ir.c index 2a33065..8e8ffb7 100644 --- a/ir.c +++ b/ir.c @@ -582,8 +582,13 @@ bool ir_values_overlap(ir_value *a, ir_value *b) /* check if the entries overlap, for that, * both must start before the other one ends. */ +#if defined(LIFE_RANGE_WITHOUT_LAST_READ) if (la->start <= lb->end && lb->start <= la->end) +#else + if (la->start < lb->end && + lb->start < la->end) +#endif { return true; } @@ -1473,14 +1478,19 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change ir_instr *instr; ir_value *value; bool tempbool; - size_t i, o, p, rd; + size_t i, o, p; /* bitmasks which operands are read from or written to */ size_t read, write; +#if defined(LIFE_RANGE_WITHOUT_LAST_READ) + size_t rd; new_reads_t new_reads; +#endif char dbg_ind[16] = { '#', '0' }; (void)dbg_ind; +#if defined(LIFE_RANGE_WITHOUT_LAST_READ) MEM_VECTOR_INIT(&new_reads, v); +#endif if (prev) { @@ -1497,16 +1507,19 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change for (p = 0; p < instr->phi_count; ++p) { value = instr->phi[p].value; - /* used this before new_reads - puts the last read into the life range as well - if (!ir_block_living_find(self, value, NULL)) - ir_block_living_add(self, value); - */ - /* fprintf(stderr, "read: %s\n", value->_name); */ +#if ! defined(LIFE_RANGE_WITHOUT_LAST_READ) + if (!ir_block_living_find(self, value, NULL) && + !ir_block_living_add(self, value)) + { + goto on_error; + } +#else if (!new_reads_t_v_find(&new_reads, value, NULL)) { if (!new_reads_t_v_add(&new_reads, value)) goto on_error; } +#endif } /* See which operands are read and write operands */ @@ -1528,16 +1541,20 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change /* read operands */ if (read & (1<_name); */ if (!new_reads_t_v_find(&new_reads, value, NULL)) { if (!new_reads_t_v_add(&new_reads, value)) goto on_error; } +#endif } /* write operands */ @@ -1547,10 +1564,15 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change */ if (write & (1<run_id == self->owner->run_id) @@ -1622,7 +1649,9 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change return true; on_error: +#if defined(LIFE_RANGE_WITHOUT_LAST_READ) MEM_VECTOR_CLEAR(&new_reads, v); +#endif return false; } From c670a8d27831b6496be569fabe6e58d0ac2460f7 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Fri, 4 May 2012 12:01:53 +0200 Subject: [PATCH 3/7] ast_loop must end by entering the outgoing block --- ast.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ast.c b/ast.c index e796215..ce89fc9 100644 --- a/ast.c +++ b/ast.c @@ -1076,6 +1076,9 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value end_bincrement = func->curblock; } + /* In any case now, we continue from the outgoing block */ + func->curblock = bout; + /* Now all blocks are in place */ /* From 'bin' we jump to whatever comes first */ if (bprecond && !ir_block_create_jump(bin, bprecond)) From 73749db6b40fb1fc35f3a7f3589074c177c12ead Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Fri, 4 May 2012 12:24:44 +0200 Subject: [PATCH 4/7] What was I thinking... fixing loop's jump creation so it doesn't try creating multiple jumps... this code is also much more readable --- ast.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/ast.c b/ast.c index ce89fc9..be69671 100644 --- a/ast.c +++ b/ast.c @@ -949,6 +949,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value ir_block *old_bcontinue; ir_block *old_bbreak; + ir_block *btemp; + (void)lvalue; (void)out; @@ -1081,14 +1083,13 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value /* Now all blocks are in place */ /* From 'bin' we jump to whatever comes first */ - if (bprecond && !ir_block_create_jump(bin, bprecond)) - return false; - else if (bbody && !ir_block_create_jump(bin, bbody)) - return false; - else if (bpostcond && !ir_block_create_jump(bin, bpostcond)) - return false; - else if ( !ir_block_create_jump(bin, bout)) + if (bprecond) tmpblock = bprecond; + else if (bbody) tmpblock = bbody; + else if (bpostcond) tmpblock = bpostcond; + else tmpblock = bout; + if (!ir_block_create_jump(bin, tmpblock)) return false; + } /* From precond */ if (bprecond) @@ -1106,27 +1107,25 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value /* from body */ if (bbody) { - if (bincrement && !ir_block_create_jump(end_bbody, bincrement)) - return false; - else if (bpostcond && !ir_block_create_jump(end_bbody, bpostcond)) - return false; - else if (bprecond && !ir_block_create_jump(end_bbody, bprecond)) - return false; - else if (!ir_block_create_jump(end_bbody, bout)) + if (bincrement) tmpblock = bincrement; + else if (bpostcond) tmpblock = bpostcond; + else if (bprecond) tmpblock = bprecond; + else tmpblock = bout; + if (!ir_block_create_jump(end_bbody, tmpblock)) return false; + } } /* from increment */ if (bincrement) { - if (bpostcond && !ir_block_create_jump(end_bincrement, bpostcond)) - return false; - else if (bprecond && !ir_block_create_jump(end_bincrement, bprecond)) - return false; - else if (bbody && !ir_block_create_jump(end_bincrement, bbody)) - return false; - else if (!ir_block_create_jump(end_bincrement, bout)) + if (bpostcond) tmpblock = bpostcond; + else if (bprecond) tmpblock = bprecond; + else if (bbody) tmpblock = bbody; + else tmpblock = bout; + if (!ir_block_create_jump(end_bincrement, tmpblock)) return false; + } } /* from postcond */ From 200b425db02c97bdacb769de2ede98d130517df0 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Fri, 4 May 2012 12:26:24 +0200 Subject: [PATCH 5/7] Fixed some dangling '}', it compiles again now --- ast.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ast.c b/ast.c index be69671..00ab611 100644 --- a/ast.c +++ b/ast.c @@ -949,7 +949,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value ir_block *old_bcontinue; ir_block *old_bbreak; - ir_block *btemp; + ir_block *tmpblock; (void)lvalue; (void)out; @@ -1089,7 +1089,6 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else tmpblock = bout; if (!ir_block_create_jump(bin, tmpblock)) return false; - } /* From precond */ if (bprecond) @@ -1113,7 +1112,6 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else tmpblock = bout; if (!ir_block_create_jump(end_bbody, tmpblock)) return false; - } } /* from increment */ @@ -1125,7 +1123,6 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else tmpblock = bout; if (!ir_block_create_jump(end_bincrement, tmpblock)) return false; - } } /* from postcond */ From 87b08247a1139444072327cfe67fa428fe1bc8e6 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Fri, 4 May 2012 12:28:35 +0200 Subject: [PATCH 6/7] A new ast-test, now using some macros to make them easier to write... --- test/ast-macros.h | 95 +++++++++++++++++++++++++++++++++++++++++++++++ test/ast-test.c | 89 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 test/ast-macros.h diff --git a/test/ast-macros.h b/test/ast-macros.h new file mode 100644 index 0000000..2f91d1f --- /dev/null +++ b/test/ast-macros.h @@ -0,0 +1,95 @@ +#ifndef TEST_AST_MACROS_HDR +#define TEST_AST_MACROS_HDR + +#if 0 +VAR(TYPE_FLOAT, i); +VAR(TYPE_FLOAT, x); + +VAR(TYPE_FLOAT, f0); +VAR(TYPE_FLOAT, f1); +VAR(TYPE_FLOAT, f5); + +MKCONSTFLOAT(f0, 0.0); +MKCONSTFLOAT(f1, 1.0); +MKCONSTFLOAT(f5, 5.0); + +STATE(ASSIGN(STORE_F, i, f0)); +WHILE(BIN(LT, i, f5)); +STATE(ASSIGN(STORE_F, x, BIN(MUL_F, i, f5))); +STATE(ASSIGN(STORE_F, i, BIN(ADD_F, i, f1))); +ENDWHILE(); +#endif + +#define TESTVARS() \ +ast_block *curblock; \ +lex_ctx ctx + +#define TESTINIT() \ +ctx.file = NULL; \ +ctx.line = 1; + +#define DEFVAR(name) \ +ast_value *name + +#define VAR(type, name) \ +name = ast_value_new(ctx, #name, type) + +#define MKGLOBAL(name) \ +assert(globals_add(name) >= 0) + +#define MKCONSTFLOAT(name, value) \ +do { \ + name->isconst = true; \ + name->constval.vfloat = value; \ + MKGLOBAL(name); \ +} while(0) + +#define STATE(a) \ +do { \ + ast_expression *exp = (ast_expression*)(a); \ + assert(ast_block_exprs_add(curblock, exp)); \ +} while(0) + +#define ASSIGN(op, a, b) \ +(ast_expression*)ast_store_new(ctx, INSTR_##op, (a), (ast_expression*)(b)) + +#define BIN(op, a, b) \ +(ast_expression*)ast_binary_new(ctx, INSTR_##op, (ast_expression*)(a), (ast_expression*)(b)) + +#define WHILE(cond) \ +do { \ + ast_expression *wh_cond = (ast_expression*)(cond); \ + ast_block *wh_body = ast_block_new(ctx); \ + ast_block *oldcur = curblock; \ + ast_loop *loop; \ + curblock = wh_body; + +#define ENDWHILE() \ + curblock = oldcur; \ + loop = ast_loop_new(ctx, NULL, (ast_expression*)wh_cond, \ + NULL, NULL, (ast_expression*)wh_body); \ + assert(loop); \ + STATE(loop); \ +} while(0) + +#define FUNCTION(name) \ +do { \ + ast_function *func_##name; \ + ast_block *my_funcblock; \ + DEFVAR(var_##name); \ + VAR(TYPE_FUNCTION, var_##name); \ + MKGLOBAL(var_##name); \ + func_##name = ast_function_new(ctx, #name, var_##name); \ + assert(functions_add(func_##name) >= 0); \ + my_funcblock = ast_block_new(ctx); \ + assert(my_funcblock); \ + assert(ast_function_blocks_add(func_##name, my_funcblock)); \ + curblock = my_funcblock; + +#define MKLOCAL(var) \ + assert(ast_block_locals_add(curblock, var)) + +#define ENDFUNCTION(name) \ +} while(0) + +#endif diff --git a/test/ast-test.c b/test/ast-test.c index 1f8a7f6..eb4e1e9 100644 --- a/test/ast-test.c +++ b/test/ast-test.c @@ -12,6 +12,7 @@ VECTOR_MAKE(ast_value*, globals); VECTOR_MAKE(ast_function*, functions); +#if 0 int main() { /* AST */ @@ -124,6 +125,94 @@ int main() assert(!"finalize on function failed..."); } + /* dump */ + ir_builder_dump(ir, printf); + + /* ir cleanup */ + ir_builder_delete(ir); + + /* cleanup */ + /* Functions must be deleted FIRST since their expressions + * reference global variables. + */ + for (i = 0; i < functions_elements; ++i) { + ast_function_delete(functions_data[i]); + } + if (functions_data) + mem_d(functions_data); + + /* We must delete not only globals, but also the functions' + * ast_values (their type and name), that's why we added them to the globals vector. + */ + for (i = 0; i < globals_elements; ++i) { + ast_value_delete(globals_data[i]); + } + if (globals_data) + mem_d(globals_data); + return 0; +} +#endif + +#include "ast-macros.h" + +int main() +{ + size_t i; + + ir_builder *ir; + + TESTVARS(); + + DEFVAR(vi); + DEFVAR(vx); + DEFVAR(f0); + DEFVAR(f1); + DEFVAR(f5); + + TESTINIT(); +VAR(TYPE_FLOAT, f0); +VAR(TYPE_FLOAT, f1); +VAR(TYPE_FLOAT, f5); +MKCONSTFLOAT(f0, 0.0); +MKCONSTFLOAT(f1, 1.0); +MKCONSTFLOAT(f5, 5.0); + +FUNCTION(main); + +VAR(TYPE_FLOAT, vi); +VAR(TYPE_FLOAT, vx); + +MKLOCAL(vi); +MKLOCAL(vx); + +STATE(ASSIGN(STORE_F, vi, f0)); +WHILE(BIN(LT, vi, f5)); +STATE(ASSIGN(STORE_F, vx, BIN(MUL_F, vi, f5))); +STATE(ASSIGN(STORE_F, vi, BIN(ADD_F, vi, f1))); +ENDWHILE(); + +ENDFUNCTION(main); + + ir = ir_builder_new("ast_test"); + assert(ir); + + /* gen globals */ + for (i = 0; i < globals_elements; ++i) { + if (!ast_global_codegen(globals_data[i], ir)) { + assert(!"failed to generate global"); + } + } + + /* gen functions */ + for (i = 0; i < functions_elements; ++i) { + if (!ast_function_codegen(functions_data[i], ir)) { + assert(!"failed to generate function"); + } + if (!ir_function_finalize(functions_data[i]->ir_func)) + assert(!"finalize on function failed..."); + } + + /* dump */ ir_builder_dump(ir, printf); From 704394c0a2f80eb2acb5ea6d0fd926d04c026124 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Fri, 4 May 2012 13:04:06 +0200 Subject: [PATCH 7/7] removing ast-test macro concept --- test/ast-macros.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/test/ast-macros.h b/test/ast-macros.h index 2f91d1f..efbf7b6 100644 --- a/test/ast-macros.h +++ b/test/ast-macros.h @@ -1,25 +1,6 @@ #ifndef TEST_AST_MACROS_HDR #define TEST_AST_MACROS_HDR -#if 0 -VAR(TYPE_FLOAT, i); -VAR(TYPE_FLOAT, x); - -VAR(TYPE_FLOAT, f0); -VAR(TYPE_FLOAT, f1); -VAR(TYPE_FLOAT, f5); - -MKCONSTFLOAT(f0, 0.0); -MKCONSTFLOAT(f1, 1.0); -MKCONSTFLOAT(f5, 5.0); - -STATE(ASSIGN(STORE_F, i, f0)); -WHILE(BIN(LT, i, f5)); -STATE(ASSIGN(STORE_F, x, BIN(MUL_F, i, f5))); -STATE(ASSIGN(STORE_F, i, BIN(ADD_F, i, f1))); -ENDWHILE(); -#endif - #define TESTVARS() \ ast_block *curblock; \ lex_ctx ctx