Browse Source

extend instruction selector syntax to allow independent destination register

cache-refactoring
Aleksey Demakov 19 years ago
parent
commit
4fe29ff197
  1. 11
      ChangeLog
  2. 2
      jit/jit-reg-alloc.h
  3. 351
      tools/gen-rules-parser.y

11
ChangeLog

@ -1,4 +1,13 @@
2006-05-20 avd <avd@buzz.wiraqocha.local>
2006-05-21 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-reg-alloc.h: add _JIT_REGS_FREE_DEST flag to be used in
cases when the destination register is independent of any input
register.
* tools/gen-rules-parser.y: allow specification of independent
destination register with '=reg' pattern syntax. (But the allocator
does not yet handle this.)
2006-05-20 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-rules-x86.c (_jit_gen_exch_top): fix computation of stack
register index.

2
jit/jit-reg-alloc.h

@ -85,6 +85,7 @@ void _jit_regs_get_reg_pair(jit_gencode_t gen, int not_this1, int not_this2,
#define _JIT_REGS_X87_ARITH 0x0020
#define _JIT_REGS_COMMUTATIVE 0x0040
#define _JIT_REGS_REVERSIBLE 0x0080
#define _JIT_REGS_FREE_DEST 0x0100
/*
* Flags for _jit_regs_init_dest(), _jit_regs_init_value1(), and
@ -145,6 +146,7 @@ typedef struct
unsigned on_stack : 1;
unsigned x87_arith : 1;
unsigned reversible : 1;
unsigned free_dest : 1;
unsigned no_pop : 1;
unsigned reverse_dest : 1;

351
tools/gen-rules-parser.y

@ -102,6 +102,11 @@ static int gensel_first_stack_reg = 8; /* st0 under x86 */
*/
#define MAX_SCRATCH 6
/*
* Maximal number of pattern elements.
*/
#define MAX_PATTERN (MAX_INPUT + MAX_SCRATCH)
/*
* Options.
*/
@ -145,8 +150,9 @@ static int gensel_first_stack_reg = 8; /* st0 under x86 */
/*
* Register flags.
*/
#define GENSEL_FLAG_CLOBBER 1
#define GENSEL_FLAG_EARLY_CLOBBER 2
#define GENSEL_FLAG_DEST 1
#define GENSEL_FLAG_CLOBBER 2
#define GENSEL_FLAG_EARLY_CLOBBER 3
/*
* Value Type.
@ -194,6 +200,9 @@ struct gensel_clause
gensel_clause_t next;
};
static char *gensel_args[] = {
"dest", "value1", "value2"
};
static char *gensel_imm_args[] = {
"insn->dest->address", "insn->value1->address", "insn->value2->address"
};
@ -206,8 +215,11 @@ static char *gensel_other_reg_names[] = {
static char *gensel_imm_names[] = {
"imm_value", "imm_value2", "imm_value3"
};
static char *gensel_local_names[] = {
"local_offset", "local_offset2", "local_offset3"
};
static char *gensel_reg_flags[] = {
"0", "_JIT_REGS_CLOBBER", "_JIT_REGS_EARLY_CLOBBER"
"0", "0", "_JIT_REGS_CLOBBER", "_JIT_REGS_EARLY_CLOBBER"
};
/*
@ -364,19 +376,20 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options
int regs, max_regs;
int other_regs_mask;
int imms, max_imms;
int have_local;
int locals, max_locals;
int scratch, others;
int have_regset;
max_regs = 0;
other_regs_mask = 0;
max_imms = 0;
have_local = 0;
max_locals = 0;
have_regset = 0;
while(clauses != 0)
{
regs = 0;
imms = 0;
locals = 0;
others = 0;
scratch = 0;
pattern = clauses->pattern;
@ -421,8 +434,7 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options
break;
case GENSEL_PATT_LOCAL:
have_local = 1;
++others;
++locals;
break;
case GENSEL_PATT_SCRATCH:
@ -439,7 +451,7 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options
}
pattern = pattern->next;
}
if((regs + imms + others) > MAX_INPUT)
if((regs + imms + locals + others) > MAX_INPUT)
{
gensel_error(
clauses->filename,
@ -461,6 +473,10 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options
{
max_imms = imms;
}
if(max_locals < locals)
{
max_locals = locals;
}
clauses = clauses->next;
}
if(max_regs > 0)
@ -511,9 +527,17 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options
printf("\tjit_nint imm_value, imm_value2, imm_value3;\n");
break;
}
if(have_local)
switch(max_locals)
{
case 1:
printf("\tjit_nint local_offset;\n");
break;
case 2:
printf("\tjit_nint local_offset, local_offset2;\n");
break;
case 3:
printf("\tjit_nint local_offset, local_offset2, local_offset3;\n");
break;
}
if(have_regset)
{
@ -521,14 +545,90 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options
}
}
/*
* Check if the pattern contains any registers.
*/
static int
gensel_contains_registers(gensel_option_t pattern)
{
while(pattern)
{
switch(pattern->option)
{
case GENSEL_PATT_REG:
case GENSEL_PATT_FREG:
case GENSEL_PATT_LREG:
case GENSEL_PATT_SCRATCH:
case GENSEL_PATT_CLOBBER:
return 1;
}
pattern = pattern->next;
}
return 0;
}
/*
* Check if the pattern contains the dest register and if it is
* defined correctly.
*/
static int
gensel_contains_free_dest(gensel_clause_t clauses, gensel_option_t pattern)
{
int found, index;
found = 0;
index = 0;
while(pattern)
{
switch(pattern->option)
{
case GENSEL_PATT_REG:
case GENSEL_PATT_FREG:
case GENSEL_PATT_LREG:
case GENSEL_PATT_LOCAL:
if(pattern->flags == GENSEL_FLAG_DEST)
{
if(index != 0)
{
gensel_error(
clauses->filename,
clauses->linenum,
"The destination must be the first pattern element.");
}
found = 1;
}
++index;
break;
case GENSEL_PATT_ANY:
case GENSEL_PATT_IMMZERO:
case GENSEL_PATT_IMM:
case GENSEL_PATT_IMMS8:
case GENSEL_PATT_IMMU8:
case GENSEL_PATT_IMMS16:
case GENSEL_PATT_IMMU16:
++index;
break;
}
pattern = pattern->next;
}
return found;
}
static void
gensel_init_names(char *names[9], char *other_names[9])
gensel_init_names(int count, char *names[], char *other_names[])
{
int index;
for(index = 0; index < 9; index++)
for(index = 0; index < count; index++)
{
names[index] = "undefined";
other_names[index] = "undefined";
if(names)
{
names[index] = "undefined";
}
if(other_names)
{
other_names[index] = "undefined";
}
}
}
@ -536,12 +636,68 @@ gensel_init_names(char *names[9], char *other_names[9])
static void
gensel_build_arg_index(
gensel_option_t pattern,
char *names[9], char *other_names[9],
int ternary)
int count,
char *names[],
char *other_names[],
int ternary,
int free_dest)
{
int index;
gensel_init_names(count, names, other_names);
index = 0;
while(pattern)
{
switch(pattern->option)
{
case GENSEL_PATT_ANY:
++index;
break;
case GENSEL_PATT_REG:
case GENSEL_PATT_FREG:
case GENSEL_PATT_LREG:
case GENSEL_PATT_LOCAL:
case GENSEL_PATT_IMMZERO:
case GENSEL_PATT_IMM:
case GENSEL_PATT_IMMS8:
case GENSEL_PATT_IMMU8:
case GENSEL_PATT_IMMS16:
case GENSEL_PATT_IMMU16:
if(ternary || free_dest)
{
if(index < 3)
{
names[index] = gensel_args[index];
}
}
else
{
if(index < 2)
{
names[index] = gensel_args[index + 1];
}
}
++index;
break;
}
pattern = pattern->next;
}
}
static void
gensel_build_imm_arg_index(
gensel_option_t pattern,
int count,
char *names[],
char *other_names[],
int ternary,
int free_dest)
{
int index;
gensel_init_names(names, other_names);
gensel_init_names(count, names, other_names);
index = 0;
while(pattern)
@ -562,7 +718,7 @@ gensel_build_arg_index(
case GENSEL_PATT_IMMU8:
case GENSEL_PATT_IMMS16:
case GENSEL_PATT_IMMU16:
if(ternary)
if(ternary || free_dest)
{
if(index < 3)
{
@ -587,15 +743,19 @@ gensel_build_arg_index(
* Build index of input value names.
*/
static void
gensel_build_var_index(gensel_option_t pattern, char *names[9], char *other_names[9])
gensel_build_var_index(
gensel_option_t pattern,
char *names[MAX_PATTERN],
char *other_names[MAX_PATTERN])
{
gensel_value_t values;
int regs, imms, index;
int regs, imms, locals, index;
gensel_init_names(names, other_names);
gensel_init_names(MAX_PATTERN, names, other_names);
regs = 0;
imms = 0;
locals = 0;
index = 0;
while(pattern)
{
@ -634,7 +794,8 @@ gensel_build_var_index(gensel_option_t pattern, char *names[9], char *other_name
break;
case GENSEL_PATT_LOCAL:
names[index] = "local_offset";
names[index] = gensel_local_names[locals];
++locals;
++index;
break;
@ -658,7 +819,9 @@ gensel_build_var_index(gensel_option_t pattern, char *names[9], char *other_name
static void
gensel_output_code(
gensel_option_t pattern,
char *code, char *names[9], char *other_names[9],
char *code,
char *names[MAX_PATTERN],
char *other_names[MAX_PATTERN],
int in_line)
{
int index;
@ -704,10 +867,15 @@ gensel_output_code(
* Output the code within a clause.
*/
static void
gensel_output_clause_code(gensel_clause_t clause, char *names[9], char *other_names[9])
gensel_output_clause_code(
gensel_clause_t clause,
char *names[MAX_PATTERN],
char *other_names[MAX_PATTERN])
{
/* Output the line number information from the original file */
#if 0
printf("#line %ld \"%s\"\n", clause->linenum, clause->filename);
#endif
gensel_output_code(clause->pattern, clause->code, names, other_names, 0);
}
@ -717,7 +885,8 @@ gensel_output_clause_code(gensel_clause_t clause, char *names[9], char *other_na
*/
static void gensel_output_clause(
gensel_clause_t clause,
char *names[9], char *other_names[9],
char *names[MAX_PATTERN],
char *other_names[MAX_PATTERN],
gensel_option_t options)
{
gensel_option_t space, more_space;
@ -770,41 +939,20 @@ static void gensel_output_clause(
}
}
static int
clause_contains_registers(gensel_clause_t clause)
{
gensel_option_t pattern;
pattern = clause->pattern;
while(pattern)
{
switch(pattern->option)
{
case GENSEL_PATT_REG:
case GENSEL_PATT_FREG:
case GENSEL_PATT_LREG:
case GENSEL_PATT_SCRATCH:
case GENSEL_PATT_CLOBBER:
return 1;
}
pattern = pattern->next;
}
return 0;
}
/*
* Output the clauses for a rule.
*/
static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t options)
{
char *args[MAX_INPUT];
char *names[9];
char *other_names[9];
char *names[MAX_PATTERN];
char *other_names[MAX_PATTERN];
gensel_clause_t clause;
gensel_option_t pattern;
gensel_value_t values, child;
int first, seen_option;
int regs, imms, scratch, index;
int clobber_all, ternary;
int regs, imms, locals, scratch, index;
int clobber_all, ternary, free_dest;
int contains_registers;
/* If the clause is manual, then output it as-is */
@ -814,7 +962,7 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
{
printf("\t_jit_regs_spill_all(gen);\n");
}
gensel_init_names(names, other_names);
gensel_init_names(MAX_PATTERN, names, other_names);
gensel_output_clause_code(clauses, names, other_names);
return;
}
@ -823,7 +971,7 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
contains_registers = 0;
while(clause)
{
contains_registers = clause_contains_registers(clause);
contains_registers = gensel_contains_registers(clause->pattern);
if(contains_registers)
{
break;
@ -842,27 +990,34 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
printf("\t_jit_regs_spill_all(gen);\n");
}
/* Determine the location of this instruction's arguments */
if(gensel_search_option(options, GENSEL_OPT_TERNARY))
{
ternary = 1;
args[0] = "dest";
args[1] = "value1";
args[2] = "value2";
}
else
{
ternary = 0;
args[0] = "value1";
args[1] = "value2";
args[2] = "??";
}
ternary = (0 != gensel_search_option(options, GENSEL_OPT_TERNARY));
/* Output the clause checking and dispatching code */
clause = clauses;
first = 1;
while(clause)
{
contains_registers = gensel_contains_registers(clause->pattern);
free_dest = gensel_contains_free_dest(clauses, clause->pattern);
clobber_all = 0;
pattern = gensel_search_option(clause->pattern, GENSEL_PATT_CLOBBER);
if(pattern)
{
values = pattern->values;
while(values)
{
if(values->value && strcmp(values->value, "*") == 0)
{
clobber_all = 1;
break;
}
values = values->next;
}
}
gensel_build_arg_index(clause->pattern, 3, args, 0, ternary, free_dest);
if(clause->next)
{
if(first)
@ -984,9 +1139,9 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
printf(" && ");
}
printf("(");
gensel_build_arg_index(
clause->pattern,
names, other_names, ternary);
gensel_build_imm_arg_index(
clause->pattern, MAX_PATTERN,
names, other_names, ternary, free_dest);
gensel_output_code(
clause->pattern,
pattern->values->value,
@ -1023,24 +1178,6 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
printf("\t\t}\n");
}
clobber_all = 0;
pattern = gensel_search_option(clause->pattern, GENSEL_PATT_CLOBBER);
if(pattern)
{
values = pattern->values;
while(values)
{
if(values->value && strcmp(values->value, "*") == 0)
{
clobber_all = 1;
break;
}
values = values->next;
}
}
contains_registers = clause_contains_registers(clause);
if(gensel_search_option(options, GENSEL_OPT_BINARY_BRANCH)
|| gensel_search_option(options, GENSEL_OPT_UNARY_BRANCH))
{
@ -1064,7 +1201,7 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
seen_option = 1;
printf("_JIT_REGS_CLOBBER_ALL");
}
if(gensel_search_option(options, GENSEL_OPT_TERNARY))
if(ternary)
{
if(seen_option)
{
@ -1076,6 +1213,18 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
}
printf("_JIT_REGS_TERNARY");
}
if(free_dest)
{
if(seen_option)
{
printf(" | ");
}
else
{
seen_option = 1;
}
printf("_JIT_REGS_FREE_DEST");
}
if(gensel_search_option(options, GENSEL_OPT_BINARY_BRANCH)
|| gensel_search_option(options, GENSEL_OPT_UNARY_BRANCH))
{
@ -1155,7 +1304,7 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
}
printf(");\n");
if(!(gensel_search_option(options, GENSEL_OPT_TERNARY)
if(!(ternary || free_dest
|| gensel_search_option(options, GENSEL_OPT_BINARY_NOTE)
|| gensel_search_option(options, GENSEL_OPT_BINARY_BRANCH)
|| gensel_search_option(options, GENSEL_OPT_UNARY_NOTE)
@ -1326,6 +1475,7 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
regs = 0;
imms = 0;
locals = 0;
index = 0;
scratch = 0;
pattern = clause->pattern;
@ -1370,9 +1520,10 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio
break;
case GENSEL_PATT_LOCAL:
printf("\t\tlocal_offset = insn->%s->frame_offset;\n",
args[index]);
index++;
printf("\t\t%s = insn->%s->frame_offset;\n",
gensel_local_names[locals], args[index]);
++locals;
++index;
break;
case GENSEL_PATT_SCRATCH:
@ -1548,7 +1699,7 @@ static void gensel_output_supported(void)
%type <code> CODE_BLOCK
%type <name> IDENTIFIER LITERAL
%type <name> IfClause IdentifierList Literal
%type <tag> OptionTag InputTag RegTag LRegTag RegFlag
%type <tag> OptionTag InputTag RegTag LRegTag RegFlag LocalTag LocalFlag
%type <clauses> Clauses Clause
%type <options> Options OptionList Pattern Pattern2
%type <option> Option PatternElement Scratch Clobber If Space
@ -1695,6 +1846,9 @@ PatternElement
: InputTag {
$$ = gensel_create_option($1, 0);
}
| LocalFlag LocalTag {
$$ = gensel_create_option_2($2, $1, 0);
}
| RegFlag RegTag {
$$ = gensel_create_option_2($2, $1, 0);
}
@ -1842,10 +1996,13 @@ InputTag
| K_IMMU8 { $$ = GENSEL_PATT_IMMU8; }
| K_IMMS16 { $$ = GENSEL_PATT_IMMS16; }
| K_IMMU16 { $$ = GENSEL_PATT_IMMU16; }
| K_LOCAL { $$ = GENSEL_PATT_LOCAL; }
| K_ANY { $$ = GENSEL_PATT_ANY; }
;
LocalTag
: K_LOCAL { $$ = GENSEL_PATT_LOCAL; }
;
RegTag
: K_REG { $$ = GENSEL_PATT_REG; }
| K_FREG { $$ = GENSEL_PATT_FREG; }
@ -1855,8 +2012,14 @@ LRegTag
: K_LREG { $$ = GENSEL_PATT_LREG; }
;
LocalFlag
: /* empty */ { $$ = 0; }
| '=' { $$ = GENSEL_FLAG_DEST; }
;
RegFlag
: /* empty */ { $$ = 0; }
| '=' { $$ = GENSEL_FLAG_DEST; }
| '*' { $$ = GENSEL_FLAG_CLOBBER; }
| '+' { $$ = GENSEL_FLAG_EARLY_CLOBBER; }
;

Loading…
Cancel
Save