Much better handling of fragments (no run-time code needed to distinguish them

from registers) and better handling of individual hops within a paragraph ---
no more ghastly hacks to try and distinguish the input from the output.
This commit is contained in:
David Given 2016-09-29 22:06:04 +02:00
parent a0131fdb47
commit 0d246c0d73
11 changed files with 97 additions and 63 deletions

View file

@ -28,10 +28,11 @@ void hop_add_string_insel(struct hop* hop, const char* string)
array_append(&hop->insels, insel); array_append(&hop->insels, insel);
} }
void hop_add_reg_insel(struct hop* hop, struct hop* reg) void hop_add_reg_insel(struct hop* hop, struct ir* ir, int insn_no)
{ {
struct insel* insel = new_insel(INSEL_REG); struct insel* insel = new_insel(INSEL_REG);
insel->u.reg = reg; insel->u.reg.ir = ir;
insel->u.reg.insn_no = insn_no;
array_append(&hop->insels, insel); array_append(&hop->insels, insel);
} }
@ -72,7 +73,7 @@ void hop_print(char k, struct hop* hop)
break; break;
case INSEL_REG: case INSEL_REG:
tracef(k, "%%%d", insel->u.reg->id); tracef(k, "$%d.%d", insel->u.reg.ir->id, insel->u.reg.insn_no);
break; break;
case INSEL_STRING: case INSEL_STRING:

View file

@ -15,7 +15,12 @@ struct insel
union union
{ {
const char* string; const char* string;
struct hop* reg; struct
{
struct ir* ir;
int insn_no;
}
reg;
struct ir* value; struct ir* value;
} }
u; u;
@ -26,15 +31,13 @@ struct hop
int id; int id;
int insn_no; int insn_no;
struct ir* ir; struct ir* ir;
struct hop* result;
ARRAYOF(struct hop) params;
ARRAYOF(struct insel) insels; ARRAYOF(struct insel) insels;
}; };
extern struct hop* new_hop(int insn_no, struct ir* ir); extern struct hop* new_hop(int insn_no, struct ir* ir);
extern void hop_add_string_insel(struct hop* hop, const char* string); extern void hop_add_string_insel(struct hop* hop, const char* string);
extern void hop_add_reg_insel(struct hop* hop, struct hop* reg); extern void hop_add_reg_insel(struct hop* hop, struct ir* ir, int insn_no);
extern void hop_add_value_insel(struct hop* hop, struct ir* ir); extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
extern void hop_add_eoi_insel(struct hop* hop); extern void hop_add_eoi_insel(struct hop* hop);
@ -42,4 +45,3 @@ extern void hop_print(char k, struct hop* hop);
#endif #endif

View file

@ -71,14 +71,14 @@ struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user)
if (cb(ir, user)) if (cb(ir, user))
return ir; return ir;
if (ir->left && !ir->left->is_sequence) if (ir->left && !ir->left->is_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_sequence) if (ir->right && !ir->right->is_root)
{ {
struct ir* irr = ir_walk(ir->right, cb, user); struct ir* irr = ir_walk(ir->right, cb, user);
if (irr) if (irr)
@ -126,7 +126,7 @@ static void print_expr(char k, const struct ir* ir)
default: default:
if (ir->left) if (ir->left)
{ {
if (ir->left->is_sequence) if (ir->left->is_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 +134,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_sequence) if (ir->right->is_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

@ -20,9 +20,9 @@ struct ir
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 */
struct hop* hop; /* only for IRs that root a hardware op */ ARRAYOF(struct hop) hops; /* only for root IRs */
bool is_sequence : 1; bool is_root : 1;
bool is_generated : 1; bool is_generated : 1;
}; };

View file

@ -6,9 +6,8 @@
static int OP_LABEL(struct ir* ir) static int OP_LABEL(struct ir* ir)
{ {
if (ir->is_generated) if (ir->is_root && ir->is_generated)
{ {
assert(ir->is_sequence);
return ir_to_esn(IR_REG, ir->size); return ir_to_esn(IR_REG, ir->size);
} }
return ir_to_esn(ir->opcode, ir->size); return ir_to_esn(ir->opcode, ir->size);

View file

@ -112,9 +112,9 @@ 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_sequence); assert(ir->is_root);
*ir = *ir->left; *ir = *ir->left;
ir->is_sequence = true; ir->is_root = true;
} }
for (i=0; i<pops.count; i++) for (i=0; i<pops.count; i++)
@ -126,7 +126,7 @@ static void convert_block(struct procedure* proc, struct basicblock* bb)
for (j=1; j<pushes.count; j++) for (j=1; j<pushes.count; j++)
phi = new_ir2(IR_PHI, ir->size, phi, pushes.item[j]); phi = new_ir2(IR_PHI, ir->size, phi, pushes.item[j]);
phi->is_sequence = ir->is_sequence; phi->is_root = ir->is_root;
*ir = *phi; *ir = *phi;
} }
} }

View file

@ -19,16 +19,9 @@ void burm_panic_cannot_match(struct ir* ir)
exit(1); exit(1);
} }
static void emit_reg(struct ir* ir) static void emit_reg(struct ir* ir, int goal)
{ {
if (ir->hop) hop_add_reg_insel(current_hop, ir, goal);
hop_add_reg_insel(current_hop, ir->hop);
else
{
const struct burm_instruction_data* insndata = &burm_instruction_data[ir->insn_no];
if (insndata->emitter)
insndata->emitter(ir, &emitter_data);
}
} }
static void emit_string(const char* data) static void emit_string(const char* data)
@ -36,6 +29,14 @@ static void emit_string(const char* data)
hop_add_string_insel(current_hop, data); hop_add_string_insel(current_hop, data);
} }
static void emit_fragment(struct ir* ir, int goal)
{
int insn_no = burm_rule(ir->state_label, goal);
const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
if (insndata->emitter)
insndata->emitter(ir, &emitter_data);
}
static void emit_value(struct ir* ir) static void emit_value(struct ir* ir)
{ {
hop_add_value_insel(current_hop, ir); hop_add_value_insel(current_hop, ir);
@ -43,7 +44,6 @@ static void emit_value(struct ir* ir)
static void emit_resultreg(void) static void emit_resultreg(void)
{ {
hop_add_reg_insel(current_hop, current_hop);
} }
static void emit_eoi(void) static void emit_eoi(void)
@ -54,6 +54,7 @@ static void emit_eoi(void)
static const struct burm_emitter_data emitter_data = static const struct burm_emitter_data emitter_data =
{ {
&emit_string, &emit_string,
&emit_fragment,
&emit_reg, &emit_reg,
&emit_value, &emit_value,
&emit_resultreg, &emit_resultreg,
@ -70,11 +71,10 @@ static void walk_instructions(struct ir* ir, int goal)
struct hop* parent_hop = NULL; struct hop* parent_hop = NULL;
int i; int i;
ir->insn_no = insn_no;
if (!insndata->is_fragment) if (!insndata->is_fragment)
{ {
parent_hop = current_hop; parent_hop = current_hop;
current_hop = ir->hop = new_hop(insn_no, ir); current_hop = new_hop(insn_no, ir);
} }
burm_kids(ir, insn_no, children); burm_kids(ir, insn_no, children);
@ -82,10 +82,11 @@ static void walk_instructions(struct ir* ir, int goal)
walk_instructions(children[i], nts[i]); walk_instructions(children[i], nts[i]);
ir->is_generated = true; ir->is_generated = true;
ir->insn_no = insn_no;
tracef('I', "I: $%d %s selected %s %d: %s\n", tracef('I', "I: $%d %s selected %s %d: %s\n",
ir->id, ir->id,
ir->is_sequence ? "S" : " ", ir->is_root ? "S" : " ",
insndata->is_fragment ? "fragment" : "instruction", insndata->is_fragment ? "fragment" : "instruction",
insn_no, insn_no,
insndata->name); insndata->name);
@ -96,12 +97,11 @@ static void walk_instructions(struct ir* ir, int goal)
insndata->emitter(ir, &emitter_data); insndata->emitter(ir, &emitter_data);
hop_print('I', current_hop); hop_print('I', current_hop);
array_append(&current_bb->hops, current_hop); array_append(&ir->hops, current_hop);
current_hop = parent_hop; current_hop = parent_hop;
} }
} }
static void select_instructions(void) static void select_instructions(void)
{ {
int i; int i;

View file

@ -1,27 +1,38 @@
REGISTERS REGISTERS
r0 GPR RET0; r0 reg4 int ret0;
r1 GPR RET1; r1 reg4 int ret1;
r2 GPR; r2 reg4 int;
r3 GPR; r3 reg4 int;
r4 GPR; r4 reg4 int;
r5 GPR; r5 reg4 int;
r6 GPR; r6 reg4 int;
r7 GPR; r7 reg4 int;
r8 GPR; r8 reg4 int;
r9 GPR; r9 reg4 int;
r10 GPR; r10 reg4 int;
r11 GPR; r11 reg4 int;
cc CC; s0 reg4 float;
s1 reg4 float;
s2 reg4 float;
s3 reg4 float;
s4 reg4 float;
s5 reg4 float;
s6 reg4 float;
s7 reg4 float;
s8 reg4 float;
s9 reg4 float;
cc conditioncode;
DECLARATIONS DECLARATIONS
address fragment; address fragment;
aluparam fragment; aluparam fragment;
reg allocates(GPR); reg allocates(reg4);
tristate allocates(CC); tristate allocates(conditioncode);
bistate allocates(CC); bistate allocates(conditioncode);
PATTERNS PATTERNS
@ -158,7 +169,8 @@ PATTERNS
aluparam = value:CONST4 aluparam = value:CONST4
emit "#$value"; emit "#$value";
aluparam = reg; aluparam = value:reg
emit "%value";
reg = value:aluparam reg = value:aluparam
emit "mov %reg, %value" emit "mov %reg, %value"
@ -175,3 +187,10 @@ PATTERNS
reg = value:CONST4 reg = value:CONST4
emit "ldr %reg, #$value" emit "ldr %reg, #$value"
cost 8; cost 8;
/* FPU operations */
reg = ADDF4(left:reg, right:reg)
emit "fadds %reg, %left, %right"
cost 4;

View file

@ -76,7 +76,7 @@ static struct ir* appendir(struct ir* ir)
int i; int i;
assert(current_bb != NULL); assert(current_bb != NULL);
ir->is_sequence = true; 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,7 +479,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_sequence) if (!v->is_root)
appendir(v); appendir(v);
push(v); push(v);
push(v); push(v);

View file

@ -295,7 +295,7 @@ struct regclass* getregclass(const char* id)
{ {
struct regclass* p = lookup(id); struct regclass* p = lookup(id);
if (!p || (p->kind != REGCLASS)) if (!p || (p->kind != REGCLASS))
yyerror("'%p' is not the name of a register class"); yyerror("'%s' is not the name of a register class", id);
return p; return p;
} }
@ -917,18 +917,22 @@ static void print_path(uint32_t path)
static const uint32_t PATH_MISSING = 0xffffffff; static const uint32_t PATH_MISSING = 0xffffffff;
static uint32_t find_label(Tree root, const char* name, uint32_t path) static uint32_t find_label(Tree root, const char* name, uint32_t path, Tree* found)
{ {
uint32_t p; uint32_t p;
if (root->label && (strcmp(root->label, name) == 0)) if (root->label && (strcmp(root->label, name) == 0))
{
if (found)
*found = root;
return path; return path;
}
p = PATH_MISSING; p = PATH_MISSING;
if (root->left && (p == PATH_MISSING)) if (root->left && (p == PATH_MISSING))
p = find_label(root->left, name, path*3 + 1); p = find_label(root->left, name, path*3 + 1, found);
if (root->right && (p == PATH_MISSING)) if (root->right && (p == PATH_MISSING))
p = find_label(root->right, name, path*3 + 2); p = find_label(root->right, name, path*3 + 2, found);
return p; return p;
} }
@ -963,15 +967,23 @@ static void emitinsndata(Rule rules)
const char* label = f->data + 1; const char* label = f->data + 1;
if (strcmp(label, r->lhs->name) == 0) if (strcmp(label, r->lhs->name) == 0)
print("%1data->emit_resultreg();\n"); print("%1data->emit_reg(node, %P%s_NT);\n", label);
else else
{ {
uint32_t path = find_label(r->pattern, label, 0); Tree node;
print("%1data->emit_reg("); uint32_t path = find_label(r->pattern, label, 0, &node);
Nonterm nt = node->op;
if (path == PATH_MISSING) if (path == PATH_MISSING)
label_not_found(r, label); label_not_found(r, label);
if (nt->is_fragment)
print("%1data->emit_fragment(");
else
print("%1data->emit_reg(");
print_path(path); print_path(path);
print(");\n"); print(", %P%s_NT);\n", ((Nonterm)node->op)->name);
} }
break; break;
} }
@ -979,7 +991,7 @@ static void emitinsndata(Rule rules)
case '$': case '$':
{ {
const char* label = f->data + 1; const char* label = f->data + 1;
uint32_t path = find_label(r->pattern, label, 0); uint32_t path = find_label(r->pattern, label, 0, NULL);
print("%1data->emit_value("); print("%1data->emit_value(");
if (path == PATH_MISSING) if (path == PATH_MISSING)
label_not_found(r, label); label_not_found(r, label);

View file

@ -27,7 +27,8 @@ extern void burm_trace(struct ir* p, int ruleno, int cost, int bestcost);
struct burm_emitter_data struct burm_emitter_data
{ {
void (*emit_string)(const char* data); void (*emit_string)(const char* data);
void (*emit_reg)(struct ir* ir); void (*emit_fragment)(struct ir* ir, int goal);
void (*emit_reg)(struct ir* ir, int goal);
void (*emit_value)(struct ir* ir); void (*emit_value)(struct ir* ir);
void (*emit_resultreg)(void); void (*emit_resultreg)(void);
void (*emit_eoi)(void); void (*emit_eoi)(void);