From: David Given Date: Mon, 26 Sep 2016 20:12:46 +0000 (+0200) Subject: Keep more data around about ir instructions. Implement a half-baked type X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=cc176e5183e5327f1c506c02cfadf09d3a7f3220;p=ack.git Keep more data around about ir instructions. Implement a half-baked type inference routine to propagate information about floats up the tree, so we know whether to put floats into special registers as early as possible. --- diff --git a/mach/proto/mcg/ir.c b/mach/proto/mcg/ir.c index f0c495f7e..9d1dab112 100644 --- a/mach/proto/mcg/ir.c +++ b/mach/proto/mcg/ir.c @@ -103,9 +103,15 @@ struct ir* ir_find(struct ir* ir, int opcode) static void print_expr(char k, const struct ir* ir) { - tracef(k, "%s", ir_names[ir->opcode]); + tracef(k, "%s", ir_data[ir->opcode].name); if (ir->size) tracef(k, "%d", ir->size); + if (ir->type) + tracef(k, ".%s", + ((ir->type == IRT_INT) ? "I" : + (ir->type == IRT_FLOAT) ? "F" : + (ir->type == IRT_ANY) ? "*" : + "?")); tracef(k, "("); switch (ir->opcode) diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index ac01f1633..79dbfdb8f 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -3,27 +3,12 @@ #include "ircodes.h" -enum -{ - IRR_LB = -1, - IRR_AB = -2, - IRR_SP = -3, - IRR_RR = -4, -}; - -enum -{ - IRS_1, - IRS_2, - IRS_4, - IRS_8 -}; - struct ir { int id; enum ir_opcode opcode; int size; + enum ir_type type; struct ir* left; struct ir* right; union diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 45bb691c6..e40bbcbf5 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -123,6 +123,7 @@ extern void pass_convert_stack_ops(struct procedure* proc); extern void pass_remove_dead_blocks(struct procedure* proc); extern void pass_eliminate_trivial_blocks(struct procedure* proc); extern void pass_instruction_selector(struct procedure* proc); +extern void pass_type_inference(struct procedure* proc); extern void procedure_compile(struct procedure* proc); diff --git a/mach/proto/mcg/pass_typeinference.c b/mach/proto/mcg/pass_typeinference.c new file mode 100644 index 000000000..4d57e3212 --- /dev/null +++ b/mach/proto/mcg/pass_typeinference.c @@ -0,0 +1,63 @@ +#include "mcg.h" + +static enum ir_type search_for_type(struct ir* ir, enum ir_type desired) +{ + const struct ir_data* data; + + if (ir->type != IRT_UNSET) + return ir->type; + + data = &ir_data[ir->opcode]; + if (ir->left) + ir->left->type = search_for_type(ir->left, data->lefttype); + if (ir->right) + ir->right->type = search_for_type(ir->right, data->righttype); + + switch (data->returntype) + { + case IRT_ANY: + if (desired == IRT_FLOAT) + ir->opcode++; + return desired; + + case IRT_UNSET: + assert(!((data->lefttype == IRT_ANY) && (data->righttype == IRT_ANY))); + if (((data->lefttype == IRT_ANY) && (ir->left->type == IRT_FLOAT)) || + ((data->righttype == IRT_ANY) && (ir->right->type == IRT_FLOAT))) + { + ir->opcode++; + return IRT_FLOAT; + } + if ((data->lefttype == IRT_ANY) && (ir->left->type == IRT_ANY)) + ir->left->type = IRT_INT; + if ((data->righttype == IRT_ANY) && (ir->right->type == IRT_ANY)) + ir->right->type = IRT_INT; + return IRT_INT; + + default: + return data->returntype; + } +} + +static void push_types_up(struct basicblock* bb) +{ + int i; + + for (i=0; iirs_count; i++) + { + struct ir* ir = bb->irs[i]; + ir->type = search_for_type(ir, ir->type); + } +} + +void pass_type_inference(struct procedure* proc) +{ + int i; + + for (i=0; iblocks_count; i++) + push_types_up(proc->blocks[i]); +} + +/* vim: set sw=4 ts=4 expandtab : */ + + diff --git a/mach/proto/mcg/procedure.c b/mach/proto/mcg/procedure.c index b0bc1a0e3..78d8f3311 100644 --- a/mach/proto/mcg/procedure.c +++ b/mach/proto/mcg/procedure.c @@ -29,6 +29,7 @@ void procedure_compile(struct procedure* proc) pass_eliminate_trivial_blocks(proc); pass_remove_dead_blocks(proc); pass_convert_stack_ops(proc); + pass_type_inference(proc); print_blocks('2', proc); diff --git a/util/mcgg/build.lua b/util/mcgg/build.lua index b3ffe81f6..83d800eaf 100644 --- a/util/mcgg/build.lua +++ b/util/mcgg/build.lua @@ -12,7 +12,7 @@ yacc { normalrule { name = "ircodes", - outleaves = { "ircodes.h", "ircodes.c" }, + outleaves = { "ircodes-dyn.h", "ircodes.c" }, ins = { "./ircodes.sh", "./ir.dat" @@ -25,10 +25,15 @@ normalrule { clibrary { name = "lib", srcs = { - matching(filenamesof("+ircodes"), "%.c$") + matching(filenamesof("+ircodes"), "%.c$"), + }, + deps = { + "+ircodes", + "./ircodes.h" }, hdrs = { matching(filenamesof("+ircodes"), "%.h$"), + "./ircodes.h", "./mcgg.h" } } diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index 9ac77edef..f29c85907 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -176,9 +176,9 @@ char* stringf(char* fmt, ...) return p; } -static void registerterminal(const char* name, int iropcode, int size) +static void registerterminal(const struct ir_data* data, int iropcode, int size) { - const char* s = (size == 0) ? name : stringf("%s%d", name, size); + const char* s = (size == 0) ? data->name : stringf("%s%d", data->name, size); int esn = ir_to_esn(iropcode, size); term(s, esn); @@ -190,15 +190,15 @@ static void registerterminals(void) for (i=0; i$header << "EOF" END { print "\tIR__COUNT" print "};" - print "" - print "enum {" - print "\tIRF_SIZED = 1" - print "};" - print "" - print "extern const char* ir_names[IR__COUNT];" - print "extern const char ir_flags[IR__COUNT];" } EOF awk -f - $in >$source << "EOF" BEGIN { print "#include \"ircodes.h\"" - print "const char* ir_names[IR__COUNT] = {" - } - - /^ *[^# ]+/ { - printf("\t\"%s\",\n", $2) + print "const struct ir_data ir_data[IR__COUNT] = {" } - END { - print "};" + function char_to_type(c) { + if (c == "I") return "IRT_INT" + if (c == "F") return "IRT_FLOAT" + if (c == "A") return "IRT_ANY" + return "IRT_UNSET" } -EOF -awk -f - $in >>$source << "EOF" - BEGIN { - print "" - print "const char ir_flags[IR__COUNT] = {" + function char_to_flags(c) { + if (c == "S") return "IRF_SIZED" + return "0" } /^ *[^# ]+/ { - if ($1 == "S") - print("\tIRF_SIZED,") - else - print("\t0,") + printf("\t{ \"%s\", ", $2) + printf("%s, ", char_to_flags(substr($1, 1, 1))) + printf("%s, ", char_to_type(substr($1, 2, 1))) + printf("%s, ", char_to_type(substr($1, 3, 1))) + printf("%s", char_to_type(substr($1, 4, 1))) + printf(" },\n") } END {