More rigorous dealing of IR groups; no need for is_generated and is_root any

more (but now passes are required to set IR roots properly when changing
instructions).
This commit is contained in:
David Given 2016-10-01 22:58:29 +02:00
parent 21898f784a
commit a3cfe6047f
11 changed files with 161 additions and 40 deletions

View file

@ -68,17 +68,18 @@ struct ir* new_localir(int offset)
struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user) struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user)
{ {
assert(ir->root);
if (cb(ir, user)) if (cb(ir, user))
return ir; 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); struct ir* irr = ir_walk(ir->left, cb, user);
if (irr) if (irr)
return 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); struct ir* irr = ir_walk(ir->right, cb, user);
if (irr) if (irr)
@ -106,7 +107,7 @@ static void print_expr(char k, const struct ir* ir)
tracef(k, "%s", ir_data[ir->opcode].name); tracef(k, "%s", ir_data[ir->opcode].name);
if (ir->size) if (ir->size)
tracef(k, "%d", ir->size); tracef(k, "%d", ir->size);
tracef(k, "("); tracef(k, ":%d(", ir->id);
switch (ir->opcode) switch (ir->opcode)
{ {
@ -123,10 +124,23 @@ static void print_expr(char k, const struct ir* ir)
tracef(k, "%s", ir->u.bvalue->name); tracef(k, "%s", ir->u.bvalue->name);
break; break;
case IR_PHI:
{
int i;
for (i=0; i<ir->u.phivalue.count; i++)
{
if (i > 0)
tracef(k, ", ");
tracef(k, "$%d", ir->u.phivalue.item[i]->id);
}
break;
}
default: default:
if (ir->left) if (ir->left)
{ {
if (ir->left->is_root) if (ir->left->root == ir->root)
tracef(k, "$%d", ir->left->id); tracef(k, "$%d", ir->left->id);
else else
print_expr(k, ir->left); print_expr(k, ir->left);
@ -134,7 +148,7 @@ static void print_expr(char k, const struct ir* ir)
if (ir->right) if (ir->right)
{ {
tracef(k, ", "); tracef(k, ", ");
if (ir->right->is_root) if (ir->right->root == ir->root)
tracef(k, "$%d", ir->right->id); tracef(k, "$%d", ir->right->id);
else else
print_expr(k, ir->right); print_expr(k, ir->right);

View file

@ -10,21 +10,20 @@ struct ir
int size; int size;
struct ir* left; struct ir* left;
struct ir* right; struct ir* right;
struct ir* root;
union union
{ {
arith ivalue; arith ivalue;
int rvalue; int rvalue;
const char* lvalue; const char* lvalue;
struct basicblock* bvalue; struct basicblock* bvalue;
ARRAYOF(struct ir) phivalue;
} u; } u;
void* state_label; /* used by the iburg instruction selector */ void* state_label; /* used by the iburg instruction selector */
int insn_no; /* the table rule number for this instruction */ int insn_no; /* the table rule number for this instruction */
int goal_no; /* the semantic type of this instruction; not stmt */ int goal_no; /* the semantic type of this instruction; not stmt */
ARRAYOF(struct hop) hops; /* only for root IRs */ ARRAYOF(struct hop) hops; /* only for root IRs */
bool is_root : 1;
bool is_generated : 1;
}; };
extern const char* ir_names[]; extern const char* ir_names[];

View file

@ -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_eliminate_trivial_blocks(struct procedure* proc);
extern void pass_instruction_selector(struct procedure* proc); extern void pass_instruction_selector(struct procedure* proc);
extern void pass_promote_float_ops(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); extern void procedure_compile(struct procedure* proc);

View file

@ -4,20 +4,13 @@
#define PANIC printf #define PANIC printf
static int OP_LABEL(struct ir* ir) #define OP_LABEL(p) burm_calculate_label(p)
{
if (ir->is_root && ir->is_generated)
{
return ir_to_esn(IR_REG, ir->size);
}
return ir_to_esn(ir->opcode, ir->size);
}
#define LEFT_CHILD(p) ((p)->left) #define LEFT_CHILD(p) ((p)->left)
#define RIGHT_CHILD(p) ((p)->right) #define RIGHT_CHILD(p) ((p)->right)
#define burm_assert(b, s) assert(b) #define burm_assert(b, s) assert(b)
extern int burm_calculate_label(struct ir* ir);
extern void burm_panic_cannot_match(struct ir* ir); extern void burm_panic_cannot_match(struct ir* ir);
static bool burm_predicate_int(struct ir* ir) static bool burm_predicate_int(struct ir* ir)

View file

@ -112,22 +112,20 @@ static void convert_block(struct procedure* proc, struct basicblock* bb)
for (i=0; i<pushes.count; i++) for (i=0; i<pushes.count; i++)
{ {
struct ir* ir = pushes.item[i]; struct ir* ir = pushes.item[i];
assert(ir->is_root);
*ir = *ir->left; *ir = *ir->left;
ir->is_root = true;
} }
for (i=0; i<pops.count; i++) for (i=0; i<pops.count; i++)
{ {
struct ir* ir = pops.item[i]; struct ir* ir = pops.item[i];
struct ir* pushir = pushes.item[0]; struct ir* phi = new_ir0(IR_PHI, ir->size);
struct ir* phi = new_ir1(IR_PHI, ir->size, pushir);
for (j=1; j<pushes.count; j++) for (j=0; j<pushes.count; j++)
phi = new_ir2(IR_PHI, ir->size, phi, pushes.item[j]); array_appendu(&phi->u.phivalue, pushes.item[j]);
phi->root = phi;
phi->is_root = ir->is_root;
*ir = *phi; *ir = *phi;
array_insert(&bb->irs, ir, 0);
} }
} }
} }

View file

@ -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; i<proc->blocks.count; i++)
{
struct basicblock* bb = proc->blocks.item[i];
int j;
for (j=0; j<bb->irs.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; i<allirs.count; i++)
{
struct ir* ir = allirs.item[i];
ir->root = NULL;
}
}
static void find_roots(void)
{
int i;
for (i=0; i<rootirs.count; i++)
{
struct ir* ir = rootirs.item[i];
assert(!ir->root);
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; i<rootirs.count; i++)
{
struct ir* ir = rootirs.item[i];
recursively_mark_root(ir, ir);
}
}
void pass_group_irs(struct procedure* proc)
{
collect_irs(proc);
clear_roots();
find_roots();
find_non_roots();
}
/* vim: set sw=4 ts=4 expandtab : */

View file

@ -2,6 +2,7 @@
static struct basicblock* current_bb; static struct basicblock* current_bb;
static struct hop* current_hop; static struct hop* current_hop;
static struct ir* current_ir;
static const struct burm_emitter_data emitter_data; static const struct burm_emitter_data emitter_data;
@ -19,6 +20,13 @@ void burm_panic_cannot_match(struct ir* ir)
exit(1); exit(1);
} }
int burm_calculate_label(struct ir* ir)
{
if (ir->root != 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) static void emit_reg(struct ir* ir, int goal)
{ {
hop_add_reg_insel(current_hop, ir, 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++) for (i=0; nts[i]; i++)
walk_instructions(children[i], nts[i]); walk_instructions(children[i], nts[i]);
ir->is_generated = true;
ir->insn_no = insn_no; ir->insn_no = insn_no;
if (goal != 1) if (goal != 1)
ir->goal_no = goal; 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->id,
ir->is_root ? "S" : " ",
ir->goal_no, ir->goal_no,
insndata->is_fragment ? "fragment" : "instruction", insndata->is_fragment ? "fragment" : "instruction",
insn_no, insn_no,
@ -114,15 +120,15 @@ static void select_instructions(void)
for (i=0; i<current_bb->irs.count; i++) for (i=0; i<current_bb->irs.count; i++)
{ {
int insnno; int insnno;
struct ir* ir = current_bb->irs.item[i]; current_ir = current_bb->irs.item[i];
burm_label(ir); burm_label(current_ir);
insnno = burm_rule(ir->state_label, 1); insnno = burm_rule(current_ir->state_label, 1);
if (!insnno) if (!insnno)
burm_panic_cannot_match(ir); burm_panic_cannot_match(current_ir);
ir_print('I', ir); ir_print('I', current_ir);
walk_instructions(ir, 1); walk_instructions(current_ir, 1);
} }
} }

View file

@ -26,6 +26,7 @@ void procedure_compile(struct procedure* proc)
print_blocks('1', proc); print_blocks('1', proc);
pass_group_irs(proc);
pass_eliminate_trivial_blocks(proc); pass_eliminate_trivial_blocks(proc);
pass_remove_dead_blocks(proc); pass_remove_dead_blocks(proc);
pass_convert_stack_ops(proc); pass_convert_stack_ops(proc);

View file

@ -1,6 +1,5 @@
#include "mcg.h" #include "mcg.h"
static struct symbol* currentproc;
static struct basicblock* current_bb; static struct basicblock* current_bb;
static int stackptr; static int stackptr;
@ -76,7 +75,6 @@ static struct ir* appendir(struct ir* ir)
int i; int i;
assert(current_bb != NULL); assert(current_bb != NULL);
ir->is_root = true;
array_append(&current_bb->irs, ir); array_append(&current_bb->irs, ir);
ir_print('0', ir); ir_print('0', ir);
@ -479,8 +477,7 @@ static void insn_ivalue(int opcode, arith value)
case op_dup: case op_dup:
{ {
struct ir* v = pop(value); struct ir* v = pop(value);
if (!v->is_root) appendir(v);
appendir(v);
push(v); push(v);
push(v); push(v);
break; break;

View file

@ -1,11 +1,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include "array.h" #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) if (array->count == array->max)
{ {
int newmax = (array->max == 0) ? 8 : (array->max * 2); int newmax = (array->max == 0) ? 8 : (array->max * 2);
@ -14,7 +13,13 @@ void array_append(void* arrayp, void* value)
array->max = newmax; array->max = newmax;
array->item = newarray; array->item = newarray;
} }
}
void array_append(void* arrayp, void* value)
{
struct array* array = arrayp;
extend(array);
array->item[array->count] = value; array->item[array->count] = value;
array->count++; array->count++;
} }
@ -40,6 +45,17 @@ bool array_appendu(void* arrayp, void* value)
return false; 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) void array_remove(void* arrayp, void* value)
{ {
struct array* array = arrayp; struct array* array = arrayp;

View file

@ -19,6 +19,7 @@ struct array
extern void array_append(void* array, void* value); extern void array_append(void* array, void* value);
extern bool array_appendu(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 void array_remove(void* array, void* value);
extern bool array_contains(void* array, void* value); extern bool array_contains(void* array, void* value);