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:
parent
21898f784a
commit
a3cfe6047f
|
@ -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; i<ir->u.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);
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -112,22 +112,20 @@ static void convert_block(struct procedure* proc, struct basicblock* bb)
|
|||
for (i=0; i<pushes.count; i++)
|
||||
{
|
||||
struct ir* ir = pushes.item[i];
|
||||
assert(ir->is_root);
|
||||
*ir = *ir->left;
|
||||
ir->is_root = true;
|
||||
}
|
||||
|
||||
for (i=0; i<pops.count; i++)
|
||||
{
|
||||
struct ir* ir = pops.item[i];
|
||||
struct ir* pushir = pushes.item[0];
|
||||
struct ir* phi = new_ir1(IR_PHI, ir->size, pushir);
|
||||
struct ir* phi = new_ir0(IR_PHI, ir->size);
|
||||
|
||||
for (j=1; j<pushes.count; j++)
|
||||
phi = new_ir2(IR_PHI, ir->size, phi, pushes.item[j]);
|
||||
for (j=0; j<pushes.count; j++)
|
||||
array_appendu(&phi->u.phivalue, pushes.item[j]);
|
||||
phi->root = phi;
|
||||
|
||||
phi->is_root = ir->is_root;
|
||||
*ir = *phi;
|
||||
array_insert(&bb->irs, ir, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
95
mach/proto/mcg/pass_groupirs.c
Normal file
95
mach/proto/mcg/pass_groupirs.c
Normal 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 : */
|
||||
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
static struct basicblock* current_bb;
|
||||
static struct hop* current_hop;
|
||||
static struct ir* current_ir;
|
||||
|
||||
static const struct burm_emitter_data emitter_data;
|
||||
|
||||
|
@ -19,6 +20,13 @@ void burm_panic_cannot_match(struct ir* ir)
|
|||
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)
|
||||
{
|
||||
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; i<current_bb->irs.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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.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)
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue