diff --git a/mach/proto/mcg/ir.c b/mach/proto/mcg/ir.c index c4755b275..d2b64b162 100644 --- a/mach/proto/mcg/ir.c +++ b/mach/proto/mcg/ir.c @@ -68,17 +68,18 @@ struct ir* new_localir(int offset) struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user) { + assert(ir->root); if (cb(ir, user)) return ir; - if (ir->left && !ir->left->is_root) + if (ir->left && (ir->left->root == ir->root)) { struct ir* irr = ir_walk(ir->left, cb, user); if (irr) return irr; } - if (ir->right && !ir->right->is_root) + if (ir->right && (ir->right->root == ir->root)) { struct ir* irr = ir_walk(ir->right, cb, user); if (irr) @@ -106,7 +107,7 @@ static void print_expr(char k, const struct ir* ir) tracef(k, "%s", ir_data[ir->opcode].name); if (ir->size) tracef(k, "%d", ir->size); - tracef(k, "("); + tracef(k, ":%d(", ir->id); switch (ir->opcode) { @@ -123,10 +124,23 @@ static void print_expr(char k, const struct ir* ir) tracef(k, "%s", ir->u.bvalue->name); break; + case IR_PHI: + { + int i; + + for (i=0; iu.phivalue.count; i++) + { + if (i > 0) + tracef(k, ", "); + tracef(k, "$%d", ir->u.phivalue.item[i]->id); + } + break; + } + default: if (ir->left) { - if (ir->left->is_root) + if (ir->left->root == ir->root) tracef(k, "$%d", ir->left->id); else print_expr(k, ir->left); @@ -134,7 +148,7 @@ static void print_expr(char k, const struct ir* ir) if (ir->right) { tracef(k, ", "); - if (ir->right->is_root) + if (ir->right->root == ir->root) tracef(k, "$%d", ir->right->id); else print_expr(k, ir->right); diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index abf4a1792..dc66ff757 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -10,21 +10,20 @@ struct ir int size; struct ir* left; struct ir* right; + struct ir* root; union { arith ivalue; int rvalue; const char* lvalue; struct basicblock* bvalue; + ARRAYOF(struct ir) phivalue; } u; void* state_label; /* used by the iburg instruction selector */ int insn_no; /* the table rule number for this instruction */ int goal_no; /* the semantic type of this instruction; not stmt */ ARRAYOF(struct hop) hops; /* only for root IRs */ - - bool is_root : 1; - bool is_generated : 1; }; extern const char* ir_names[]; diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index ddd33aecf..3db29b86c 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -125,6 +125,7 @@ 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_promote_float_ops(struct procedure* proc); +extern void pass_group_irs(struct procedure* proc); extern void procedure_compile(struct procedure* proc); diff --git a/mach/proto/mcg/mcgg_generated_header.h b/mach/proto/mcg/mcgg_generated_header.h index b37fe8cd3..eead127f1 100644 --- a/mach/proto/mcg/mcgg_generated_header.h +++ b/mach/proto/mcg/mcgg_generated_header.h @@ -4,20 +4,13 @@ #define PANIC printf -static int OP_LABEL(struct ir* ir) -{ - if (ir->is_root && ir->is_generated) - { - return ir_to_esn(IR_REG, ir->size); - } - return ir_to_esn(ir->opcode, ir->size); -} - +#define OP_LABEL(p) burm_calculate_label(p) #define LEFT_CHILD(p) ((p)->left) #define RIGHT_CHILD(p) ((p)->right) #define burm_assert(b, s) assert(b) +extern int burm_calculate_label(struct ir* ir); extern void burm_panic_cannot_match(struct ir* ir); static bool burm_predicate_int(struct ir* ir) diff --git a/mach/proto/mcg/pass_convertstackops.c b/mach/proto/mcg/pass_convertstackops.c index 285ca1626..c34eddf16 100644 --- a/mach/proto/mcg/pass_convertstackops.c +++ b/mach/proto/mcg/pass_convertstackops.c @@ -112,22 +112,20 @@ static void convert_block(struct procedure* proc, struct basicblock* bb) for (i=0; iis_root); *ir = *ir->left; - ir->is_root = true; } for (i=0; isize, pushir); + struct ir* phi = new_ir0(IR_PHI, ir->size); - for (j=1; jsize, phi, pushes.item[j]); + for (j=0; ju.phivalue, pushes.item[j]); + phi->root = phi; - phi->is_root = ir->is_root; *ir = *phi; + array_insert(&bb->irs, ir, 0); } } } diff --git a/mach/proto/mcg/pass_groupirs.c b/mach/proto/mcg/pass_groupirs.c new file mode 100644 index 000000000..833809b1d --- /dev/null +++ b/mach/proto/mcg/pass_groupirs.c @@ -0,0 +1,95 @@ +#include "mcg.h" + +static ARRAYOF(struct ir) allirs; +static ARRAYOF(struct ir) rootirs; + +static void addall(struct ir* ir) +{ + if (array_appendu(&allirs, ir)) + return; + + if (ir->left) + addall(ir->left); + if (ir->right) + addall(ir->right); +} + +static void collect_irs(struct procedure* proc) +{ + int i; + + allirs.count = rootirs.count = 0; + for (i=0; iblocks.count; i++) + { + struct basicblock* bb = proc->blocks.item[i]; + int j; + + for (j=0; jirs.count; j++) + { + struct ir* ir = bb->irs.item[j]; + addall(ir); + array_appendu(&rootirs, ir); + } + } +} + +static void clear_roots(void) +{ + int i; + + for (i=0; iroot = NULL; + } +} + +static void find_roots(void) +{ + int i; + + for (i=0; iroot); + ir->root = ir; + } +} + +static void recursively_mark_root(struct ir* node, struct ir* root) +{ + if (node != root) + { + if (node->root) + return; + node->root = root; + } + + if (node->left) + recursively_mark_root(node->left, root); + if (node->right) + recursively_mark_root(node->right, root); +} + +static void find_non_roots(void) +{ + int i; + + for (i=0; iroot != current_ir) + return ir_to_esn(IR_REG, ir->size); + return ir_to_esn(ir->opcode, ir->size); +} + static void emit_reg(struct ir* ir, int goal) { hop_add_reg_insel(current_hop, ir, goal); @@ -81,14 +89,12 @@ static void walk_instructions(struct ir* ir, int goal) for (i=0; nts[i]; i++) walk_instructions(children[i], nts[i]); - ir->is_generated = true; ir->insn_no = insn_no; if (goal != 1) ir->goal_no = goal; - tracef('I', "I: $%d %s goal %d selected %s %d: %s\n", + tracef('I', "I: $%d goal %d selected %s %d: %s\n", ir->id, - ir->is_root ? "S" : " ", ir->goal_no, insndata->is_fragment ? "fragment" : "instruction", insn_no, @@ -114,15 +120,15 @@ static void select_instructions(void) for (i=0; iirs.count; i++) { int insnno; - struct ir* ir = current_bb->irs.item[i]; - burm_label(ir); + current_ir = current_bb->irs.item[i]; + burm_label(current_ir); - insnno = burm_rule(ir->state_label, 1); + insnno = burm_rule(current_ir->state_label, 1); if (!insnno) - burm_panic_cannot_match(ir); + burm_panic_cannot_match(current_ir); - ir_print('I', ir); - walk_instructions(ir, 1); + ir_print('I', current_ir); + walk_instructions(current_ir, 1); } } diff --git a/mach/proto/mcg/procedure.c b/mach/proto/mcg/procedure.c index 300882eb9..dc11e0a43 100644 --- a/mach/proto/mcg/procedure.c +++ b/mach/proto/mcg/procedure.c @@ -26,6 +26,7 @@ void procedure_compile(struct procedure* proc) print_blocks('1', proc); + pass_group_irs(proc); pass_eliminate_trivial_blocks(proc); pass_remove_dead_blocks(proc); pass_convert_stack_ops(proc); diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 58f19bdc2..8835c0b46 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -1,6 +1,5 @@ #include "mcg.h" -static struct symbol* currentproc; static struct basicblock* current_bb; static int stackptr; @@ -76,7 +75,6 @@ static struct ir* appendir(struct ir* ir) int i; assert(current_bb != NULL); - ir->is_root = true; array_append(¤t_bb->irs, ir); ir_print('0', ir); @@ -479,8 +477,7 @@ static void insn_ivalue(int opcode, arith value) case op_dup: { struct ir* v = pop(value); - if (!v->is_root) - appendir(v); + appendir(v); push(v); push(v); break; diff --git a/modules/src/data/array.c b/modules/src/data/array.c index 8943323cb..bfaaf8e84 100644 --- a/modules/src/data/array.c +++ b/modules/src/data/array.c @@ -1,11 +1,10 @@ #include #include +#include #include "array.h" -void array_append(void* arrayp, void* value) +static void extend(struct array* array) { - struct array* array = arrayp; - if (array->count == array->max) { int newmax = (array->max == 0) ? 8 : (array->max * 2); @@ -14,7 +13,13 @@ void array_append(void* arrayp, void* value) array->max = newmax; array->item = newarray; } +} +void array_append(void* arrayp, void* value) +{ + struct array* array = arrayp; + + extend(array); array->item[array->count] = value; array->count++; } @@ -40,6 +45,17 @@ bool array_appendu(void* arrayp, void* value) return false; } +void array_insert(void* arrayp, void* value, int before) +{ + struct array* array = arrayp; + + extend(array); + memmove(&array->item[before+1], &array->item[before], + (array->count-before) * sizeof(*array)); + array->item[before] = value; + array->count++; +} + void array_remove(void* arrayp, void* value) { struct array* array = arrayp; diff --git a/modules/src/data/array.h b/modules/src/data/array.h index 601873571..63951ff5d 100644 --- a/modules/src/data/array.h +++ b/modules/src/data/array.h @@ -19,6 +19,7 @@ struct array extern void array_append(void* array, void* value); extern bool array_appendu(void* array, void* value); +extern void array_insert(void* array, void* value, int before); extern void array_remove(void* array, void* value); extern bool array_contains(void* array, void* value);