blob: 50a26fb024a5440d7edd37baf7e4ab282054b589 [file] [log] [blame]
/* Loop Vectorization using unified representation for permute instructions.
Copyright (C) 2003-2015 Free Software Foundation, Inc.
Contributed by Sameera Deshpande <sameera.deshpande@imgtec.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#define GENERATOR_FILE 1
#include "bconfig.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "errors.h"
#ifdef GENERATOR_FILE
#include "machmode.h"
#include "signop.h"
#include "wide-int.h"
#include "double-int.h"
#include "real.h"
#include "fixed-value.h"
#include "statistics.h"
#include "vec.h"
#include "hash-table.h"
#include "hash-set.h"
#include "input.h"
#include "is-a.h"
#include "target.h"
#endif
#include "tree-core.h"
#include "tree-vect-unified.h"
//#include "tree-vect-unified-common.c"
//#include "tree-vect-unified-opts.c"
#define DEBUG 0
int target_flags;
enum rule_type {NT2T, NT2NT, NT2OP};
/* Normalized context free grammar of the form
NT --> T
NT--> NT
NT --> OP (<list of NTs>) */
struct grammar_rule
{
/* Pointer to vec_perm_order_spec corresponding to grammar rule. For default
rules, this value is NULL. */
struct vec_perm_order_spec *porder;
/* Non-terminal on LHS. */
int lhs_nt;
enum rule_type type;
int spec_idx;
int cost;
union {
/* Terminal on RHS. */
int terminal;
/* Non-terminal on RHS. */
int non_terminal;
/* RHS of the form OP_div,sel (NT1, NT2...NTk) for k_arity operation op. */
struct rhs_expression {
struct operation {
enum primop_code op;
int opd_selector;
int division;
int out_type;
tree *var_stride;
} primop;
vec<int> rhs_nt;
} rhs_exp;
} u;
};
struct vec_perm_order_spec target_spec[] = TARGET_VEC_PERM_CONST_ORDER;
vec <struct grammar_rule *> rules;
int default_extr_2_0, default_extr_2_1, default_ilv_2;
int name_idx = 0;
struct non_terminal
{
char *str;
vec <int> nt_on_lhs_rules;
vec <int> nt_on_rhs_rules;
int state;
int type;
};
struct terminal
{
char *str;
int state;
int type;
};
/* List of non-terminals used in grammar. The index is used in the grammar rule
to point to appropriate non-terminal in the list. For now, the non-terminal
is just list of strings with NT names. However if needed, it can be updated
to hold additional information in the structure. */
vec<struct non_terminal *> non_terminals;
/* List of terminals in Grammar. Currently, we support only 3 categories in
terminals -
MEM, REG and CONST. */
vec<struct terminal *>terminals;
struct transition_state
{
int id;
vec<int> nt;
vec<int> rule;
vec<int> cost;
};
vec<struct transition_state *> states;
vec<int> arity_list;
struct operator_info
{
/* Permute operation. */
enum primop_code pcode;
/* Arity of operator. */
int arity;
/* Actual arity of operator. */
int act_arity;
/* Selector of the operator. */
int sel;
/* Type of operator. */
int type;
/* Projection Map for ith operand of operator w.r.t. state. */
vec<struct transition_state *> map[10];
vec<long long> index_map;
vec<int>trans_map;
vec<int> state_map;
vec<struct transition_state *> rep_states[10];
};
/* Function create_placeholder.
*/
struct primop_tree *
create_placeholder (int idx, char ch, struct primop_tree *parent)
{
struct primop_tree *ptree;
ptree = populate_prim_node (POP_PH, NULL,
parent, NULL, NULL);
PT_PH_IDX (ptree) = idx;
PT_PH_TYPE (ptree) = ch;
return ptree;
}
/* Function create_perm_order_tree.
For each element in TARGET_VEC_PERM_CONST_ORDER
Do
1. Create ILV node with arity out_vec_size.
2. For ith element in perm_order
Do
1. Create EXTR node with parts = in_vec_size and selector = i % parts
2. Create child of EXTR as PLACEHOLDER_<M|C|R>_<i / parts>, i / parts
should not exceed num_opd. For k_arity_promotion_reduction and
unity_redundancy_elimination, PLACEHOLDER_<M|C|R>_<num> is used for
matching. Whereas for grammar definition, only PLACEHOLDER_<M|C|R>
is used for generating rules.
Done
Done
*/
struct primop_tree *
create_perm_order_tree (struct vec_perm_order_spec spec)
{
int i, num;
struct primop_tree *ilv_node, *expr_node, *placeholder;
ilv_node = create_primTree_combine (POP_ILV, NULL,
spec.out_vec_size, NULL, NULL, NULL);
for (i = 0; i < spec.out_vec_size; i++)
{
expr_node = create_primTree_partition (POP_EXTR, NULL,
spec.in_vec_size, spec.perm_order[i] % spec.in_vec_size,
NULL, ilv_node, NULL);
num = spec.perm_order[i] / spec.in_vec_size;
placeholder = create_placeholder (num,
spec.opd_constraint[num], expr_node);
add_child_at_index (expr_node, placeholder, 0);
add_child_at_index (ilv_node, expr_node, i);
}
return ilv_node;
}
/* Function print_perm_order.
*/
void print_perm_order (int *perm_order, int num)
{
int i;
for (i = 0; i < num; i++)
printf (" %d ", perm_order[i]);
}
/* Function print_instruction_tile.
*/
void
print_instruction_tile (struct primop_tree *ptree, int tab = 0)
{
int i;
if (PT_NODE_OP (ptree) != POP_PH)
{
printf ("\n");
for (i = 0; i < tab; i++)
printf (" ");
}
switch (PT_NODE_OP (ptree))
{
case POP_EXTR:
printf ("EXTR_%d,%d (", PT_DIVISION (ptree),
PT_OPERAND_SELECTOR (ptree));
print_instruction_tile (PT_CHILD (ptree, 0), tab + 2);
printf (")");
break;
case POP_ILV:
printf ("ILV_%d (", PT_DIVISION (ptree));
for (i = 0; i < PT_DIVISION (ptree) - 1; i++)
{
print_instruction_tile (PT_CHILD (ptree, i), tab + 2);
printf (" , ");
}
print_instruction_tile (PT_CHILD (ptree, i), tab + 2);
printf (")");
break;
case POP_PH:
printf ("PH%c:%d", PT_PH_TYPE (ptree), PT_PH_IDX (ptree));
break;
default:
gcc_assert (!"\nUndesired case in printing tree.\n");
return;
}
}
/* Function print_instruction_tiles.
*/
void
print_instruction_tiles ()
{
int i;
printf ("/*");
for (i = 0; i < sizeof (target_spec)/sizeof (struct vec_perm_order_spec); i++)
{
printf ("\n\npermute order - ");
print_perm_order (target_spec[i].perm_order, target_spec[i].out_vec_size);
print_instruction_tile (target_spec[i].ptree);
}
printf ("*/\n\n");
}
/* Function create_instruction_tiles.
For each permute_order in TARGET_VEC_PERM_CONST_ORDER
Do
1. Create permute order tree from permute order - the permute order tree
so created is of arity out_vec_size.
2. Perform k_arity_promotion_reduction on permute order tree to reduce the
arity to 2. As out_vec_size is power of 2, the promotion/reduction is
never going to fail.
3. Perform unity_redundancy_elimination of kind
ILV_m (EXTR_0(S), EXTR_1(S),...EXTR_m-1(S)) => S
EXTR_m,x (ILV_M(S1, S2, ... Sm)) => Sx
to get optimal permute order tree.
Done
*/
void
create_instruction_tiles ()
{
int i;
struct primop_tree *ptree;
arity_list = vNULL;
arity_list.safe_insert (0, 2);
for (i = 0; i < sizeof (target_spec)/sizeof (struct vec_perm_order_spec); i++)
{
ptree = create_perm_order_tree (target_spec[i]);
ptree = k_arity_promotion_reduction (ptree, 2);
ptree = unity_redundancy_elimination (ptree);
target_spec[i].ptree = ptree;
}
}
/* Function get_term_index.
Return index of terminal.
*/
int
get_term_index (vec<struct terminal *> *worklist, char *str, int type)
{
int i;
for (i = 0; i < worklist->length (); i++)
{
if (type == (*worklist)[i]->type && !strcmp ((*worklist)[i]->str, str))
return i;
}
return -1;
}
/* Function get_index.
Return index of non-terminal.
*/
int
get_index (vec<struct non_terminal *> *worklist, char *str, int type)
{
int i;
for (i = 0; i < worklist->length (); i++)
{
if (type == (*worklist)[i]->type && !strcmp ((*worklist)[i]->str, str))
return i;
}
return -1;
}
/* Function create_non_terminal.
*/
int
create_non_terminal (char *str, int type)
{
int idx;
struct non_terminal *buf;
idx = get_index (&non_terminals, str, type);
if (idx != -1)
return idx;
idx = non_terminals.length ();
buf = (struct non_terminal *) xcalloc (1, sizeof (struct non_terminal));
buf->str = (char *) xcalloc (strlen (str), sizeof (char));
strcpy (buf->str, str);
buf->nt_on_lhs_rules = vNULL;
buf->nt_on_rhs_rules = vNULL;
buf->state = -1;
non_terminals.safe_insert (idx, buf);
non_terminals[idx]->type = type;
return idx;
}
/* Function create_rule_NT_to_NT.
Creates grammar rule of kind NT --> NT for normalized grammar.
*/
int
create_rule_NT_to_NT (int lhs_nt, int rhs_nt, int off, int cost)
{
struct grammar_rule * rule;
int ruleno;
gcc_assert (non_terminals[lhs_nt]->type == non_terminals[rhs_nt]->type);
rule = (struct grammar_rule *) xcalloc (1, sizeof (struct grammar_rule));
rule->lhs_nt = lhs_nt;
rule->type = NT2NT;
rule->u.non_terminal = rhs_nt;
rule->spec_idx = off;
if (off != -1)
rule->cost = target_spec[off].cost;
else
rule->cost = cost;
ruleno = rules.length ();
rules.safe_insert (ruleno, rule);
non_terminals[lhs_nt]->nt_on_lhs_rules.safe_insert (
non_terminals[lhs_nt]->nt_on_lhs_rules.length (), ruleno);
non_terminals[rhs_nt]->nt_on_rhs_rules.safe_insert (
non_terminals[rhs_nt]->nt_on_rhs_rules.length (), ruleno);
return ruleno;
}
int lookup_NT2T_in_grammar (vec <struct grammar_rule *> *, char *, int);
/* Function create_rule_NT_to_T.
Creates grammar rule of kind NT --> T for normalized grammar.
*/
int
create_rule_NT_to_T (int lhs_nt, int rhs_t, int off, int cost = 8)
{
struct grammar_rule * rule;
int ruleno;
ruleno = lookup_NT2T_in_grammar (&rules, non_terminals[lhs_nt]->str, rhs_t);
if (ruleno != -1)
return ruleno;
gcc_assert (non_terminals[lhs_nt]->type == terminals[rhs_t]->type);
rule = (struct grammar_rule *) xcalloc (1, sizeof (struct grammar_rule));
rule->lhs_nt = lhs_nt;
rule->type = NT2T;
rule->u.terminal = rhs_t;
rule->spec_idx = off;
if (off != -1)
rule->cost = target_spec[off].cost;
else
rule->cost = cost;
ruleno = rules.length ();
rules.safe_insert (ruleno, rule);
non_terminals[lhs_nt]->nt_on_lhs_rules.safe_insert (
non_terminals[lhs_nt]->nt_on_lhs_rules.length (), ruleno);
return ruleno;
}
/* Function create_rule_NT_to_op_tree.
Creates grammar rule of kind NT --> OP (NT1, NT2 ...) for normalized grammar.
*/
int
create_rule_NT_to_op_tree (int lhs_nt, enum primop_code op, int selector,
int division, int *rhs_opd, int length, int off,
int otype, int cost=-1)
{
struct grammar_rule * rule;
int ruleno;
int i;
rule = (struct grammar_rule *) xcalloc (1, sizeof (struct grammar_rule));
rule->lhs_nt = lhs_nt;
rule->type = NT2OP;
rule->u.rhs_exp.primop.op = op;
rule->u.rhs_exp.primop.opd_selector = selector;
rule->u.rhs_exp.primop.division = division;
rule->u.rhs_exp.primop.out_type = otype;
rule->u.rhs_exp.primop.var_stride = NULL;
rule->spec_idx = off;
if (off != -1)
rule->cost = target_spec[off].cost;
else if (cost != -1)
rule->cost = cost;
else
rule->cost = (op == POP_EXTR ? 8 : 16);//rules[default_ilv_2]->cost);
for (i = 0; i < length; i++)
{
rule->u.rhs_exp.rhs_nt.safe_insert (i, rhs_opd[i]);
}
ruleno = rules.length ();
rules.safe_insert (ruleno, rule);
non_terminals[lhs_nt]->nt_on_lhs_rules.safe_insert (
non_terminals[lhs_nt]->nt_on_lhs_rules.length (), ruleno);
return ruleno;
}
int
create_terminal (char *str, int type)
{
struct terminal *buf;
int idx;
idx = get_term_index (&terminals, str, type);
if (idx != -1)
return idx;
buf = (struct terminal *) xcalloc (1, sizeof (struct terminal));
buf->str = (char *) xcalloc (strlen(str)+1, sizeof (char));
strcpy (buf->str, str);
buf->state = -1;
idx = terminals.length ();
terminals.safe_insert (idx, buf);
terminals[idx]->type = type;
return idx;
}
vec<char *> type_name = vNULL;
int
lookup_type (vec<char *> *type_name, char *type)
{
int i;
for (i = 0; i < type_name->length (); i++)
{
if (!strcmp (type, (*type_name)[i]))
return i;
}
char *str = (char *) xcalloc (1, strlen (type));
strcpy (str, type);
type_name->safe_insert (i, str);
return i;
}
/* Function create_terminals.
*/
void
create_terminals ()
{
struct terminal *buf;
int idx, mem, consti;
int vec_size, vector_sizes, max_vec_size, i;
int type;
vector_sizes = MAX_VECTOR_SIZE;
max_vec_size = 1 << floor_log2 (vector_sizes);
vec_size = max_vec_size;
// for (i = 0; i < floor_log2 (max_vec_size); i++)
for (i = 0; i < sizeof (target_spec)/sizeof (struct vec_perm_order_spec); i++)
{
char buf[20];
int idx;
type = lookup_type (&type_name, target_spec[i].type);
sprintf (buf, "MEM_%s", target_spec[i].type);
mem = create_terminal (buf, type);
sprintf (buf, "mem_%s", target_spec[i].type);
create_rule_NT_to_T (create_non_terminal (buf, type), mem, -1);
sprintf (buf, "CONST_%s", target_spec[i].type);
consti = create_terminal (buf, type);
sprintf (buf, "const_%s", target_spec[i].type);
create_rule_NT_to_T (create_non_terminal (buf, type), consti, -1);
sprintf (buf, "REG_%s", target_spec[i].type);
idx = create_terminal (buf, type);
sprintf (buf, "reg_%s", target_spec[i].type);
create_rule_NT_to_T (create_non_terminal (buf, type), idx, -1);
create_rule_NT_to_T (create_non_terminal (buf, type), mem, -1);
create_rule_NT_to_T (create_non_terminal (buf, type), consti, -1);
}
return;
}
/* Function create_default_rules.
Default rules Costs
================================
goal --> reg (0)
goal --> mem (0)
reg --> mem (10)
reg --> const (5)
mem --> reg (10)
mem --> const (8)
:
:
reg_32 --> REG (0)
reg_16 --> REG (0)
reg_8 --> REG (0)
reg_4 --> REG (0)
reg_2 --> REG (0)
reg -> reg_2 (0)
reg -> reg_4 (0)
reg -> reg_8 (0)
reg -> reg_16 (0)
reg -> reg_32 (0)
:
:
mem --> MEM (0)
const --> CONST (0)
reg --> EXTR_2,0 (reg) (1)
reg --> EXTR_2,1 (reg) (1)
reg --> ILV (reg, reg) (2)
*/
void
create_default_rules ()
{
int goal, reg, mem, consti;
int i, vec_size, max_vec_size, vector_sizes;
int v[2];
create_terminals ();
return;
}
/* Function lookup_NT2T_in_grammar.
Look-up similar rule in rule-list.
*/
int
lookup_NT2T_in_grammar (vec <struct grammar_rule *> *rule,
char *nt_substr, int t_idx)
{
int i;
if (*rule == vNULL)
return -1;
for (i = 0; i < rule->length (); i++)
{
struct grammar_rule *r;
rule->iterate (i, &r);
if (r->u.terminal == t_idx
&& (strstr (non_terminals[r->lhs_nt]->str, nt_substr)))
return i;
}
return -1;
}
/* Function lookup_NT2OP_in_grammar.
Look-up rule matching operation OP and children in vector nt_list.
*/
int
lookup_NT2OP_in_grammar (vec <struct grammar_rule *> *rule,
enum primop_code code, int sel, int div, int otype,
int *nt_list, int length)
{
int i, j;
if (*rule == vNULL)
return -1;
for (i = 0; i < rule->length (); i++)
{
struct grammar_rule *r;
rule->iterate (i, &r);
if (r->u.rhs_exp.primop.op == code
&& sel == r->u.rhs_exp.primop.opd_selector
&& div == r->u.rhs_exp.primop.division
&& otype == r->u.rhs_exp.primop.out_type)
{
for (j = 0; j < length; j++)
{
if (nt_list[j] != r->u.rhs_exp.rhs_nt[j])
break;
}
if (j == length)
return i;
}
}
return -1;
}
/* Function create_rule_for_ptree.
Recursive function to create grammar rules in normal form.
If the leaf node with placeholder :
- check if the rule is already present.
If yes, return the previously created non-terminal
Otherwise, create new non-terminal for the place-holder, with appropriate
vector size, and create rules of the form
<new_nt> --> <REG|MEM|CONST>
<reg_<vecsize>|mem|const> --> <new_nt>
If non-leaf node,
- For each child of the node invoke the function recursively.
- Once all children are processed, check if the rule with current primop
and children is already present.
If yes, return previously created non-terminal for corresponding rule.
Otherwise, create non-terminal for out_vecsize and create rules of the
form
<new_nt> --> PRIMOP (<list of NTs corresponding to respective child>)
<reg_<vecsize>|mem|const> --> <new_nt>
*/
int
create_rule_for_ptree (struct primop_tree *ptree, int spec_idx, int out_vecsize,
int in_vecsize, int target_type, int type)
{
int chld_nt[30];
char buf[20], name[20], buf1[20], buf2[20];
int found, nt, new_in_vec_size, i, ruleno;
if (PT_NODE_OP (ptree) == POP_PH)
{
sprintf (buf, "reg_%s", type_name[type]);
sprintf (buf1, "mem_%s", type_name[type]);
sprintf (buf2, "const_%s", type_name[type]);
return create_non_terminal (PT_PH_TYPE (ptree) == 'R' ? (char *) buf
: PT_PH_TYPE (ptree) == 'M' ? (char *) buf1
: (char *)buf2, type);
}
if (PT_NODE_OP (ptree) == POP_ILV)
new_in_vec_size = in_vecsize / PT_DIVISION (ptree);
if (PT_NODE_OP (ptree) == POP_EXTR)
new_in_vec_size = in_vecsize * PT_DIVISION (ptree);
for (i = 0; i < ptree->children.length (); i++)
{
chld_nt[i] = create_rule_for_ptree (PT_CHILD (ptree, i),
-1, in_vecsize, new_in_vec_size, target_type, type);
}
found = lookup_NT2OP_in_grammar (&rules,
(enum primop_code) PT_NODE_OP (ptree),
PT_OPERAND_SELECTOR (ptree),
PT_DIVISION (ptree), type, chld_nt, i);
if (found != -1)
{
return (rules)[found]->lhs_nt;
}
else
{
/* Create new NT, and create rule NT_to_OP. */
sprintf (name, "inter%d", name_idx++);
nt = create_non_terminal (name, type);
ruleno = create_rule_NT_to_op_tree (nt,
(enum primop_code) PT_NODE_OP (ptree),
PT_OPERAND_SELECTOR (ptree), PT_DIVISION (ptree),
chld_nt, i, spec_idx, type);
if (spec_idx == -1)
{
//ruleno = create_rule_NT_to_NT (create_non_terminal ("reg"), nt, -1, 0);
}
if (spec_idx != -1)
{
sprintf (buf, "reg_%s", type_name[type]);
ruleno = create_rule_NT_to_NT (
create_non_terminal (buf, type),
nt, -1, 0);
}
return nt;
}
}
void
create_default_op_rules ()
{
int goal, reg, mem, consti;
int i, j, vec_size, max_vec_size, vector_sizes;
int v[2];
int chld_nt[4];
char name[20];
int found, nt, ruleno;
/* For each vector type supported, add NT2T rule for
reg. */
vector_sizes = MAX_VECTOR_SIZE;
max_vec_size = 1 << floor_log2 (vector_sizes);
vec_size = max_vec_size >> 1;
for (i = 0; i < type_name.length (); i++)
{
char buf[20];
int idx;
sprintf (buf, "reg_%s", type_name[i]);
idx = create_non_terminal (buf, i);
for (j = 0; j < 2; j++)
{
chld_nt[j] = idx;
}
found = lookup_NT2OP_in_grammar (&rules, POP_ILV, -1,
2, i, chld_nt, 2);
if (found == -1)
{
/* Create new NT, and create rule NT_to_OP. */
sprintf (name, "inter%d", name_idx++);
nt = create_non_terminal (name, i);
ruleno = create_rule_NT_to_op_tree (nt, POP_ILV, -1, 2,
chld_nt, 2, -1, i);
ruleno = create_rule_NT_to_NT (idx, nt, -1, 0);
}
else
{
ruleno = create_rule_NT_to_NT (idx, rules[found]->lhs_nt, -1, 0);
}
found = lookup_NT2OP_in_grammar (&rules, POP_EXTR, 0,
2, i, chld_nt, 1);
if (found == -1)
{
/* Create new NT, and create rule NT_to_OP. */
sprintf (name, "inter%d", name_idx++);
nt = create_non_terminal (name, i);
ruleno = create_rule_NT_to_op_tree (nt, POP_EXTR, 0, 2,
chld_nt, 1, -1, i);
ruleno = create_rule_NT_to_NT (idx, nt, -1, 0);
}
else
{
ruleno = create_rule_NT_to_NT (idx, rules[found]->lhs_nt, -1, 0);
}
found = lookup_NT2OP_in_grammar (&rules, POP_EXTR, 1,
2, i, chld_nt, 1);
if (found == -1)
{
/* Create new NT, and create rule NT_to_OP. */
sprintf (name, "inter%d", name_idx++);
nt = create_non_terminal (name, i);
ruleno = create_rule_NT_to_op_tree (nt, POP_EXTR, 1, 2,
chld_nt, 1, -1, i);
ruleno = create_rule_NT_to_NT (idx, nt, -1, 0);
}
else
{
ruleno = create_rule_NT_to_NT (idx, rules[found]->lhs_nt, -1, 0);
}
}
return;
}
/* Function create_grammar_rules.
Creates grammar rules for each primop_tree.
*/
void
create_grammar_rules ()
{
int i;
rules = vNULL;
non_terminals = vNULL;
terminals = vNULL;
create_default_rules ();
for (i = 0;
i < sizeof (target_spec)/sizeof (struct vec_perm_order_spec);
i++)
{
int idx = 0;
create_rule_for_ptree (target_spec[i].ptree, i,
target_spec[i].out_vec_size,
target_spec[i].in_vec_size,
target_spec[i].opd_constraint[0],
lookup_type(&type_name, (target_spec[i].type)));
}
create_default_op_rules ();
}
/* Function print_rule_operands.
*/
void
print_rule_operands (vec<int> *arr)
{
int i;
printf ("%s", non_terminals[(*arr)[0]]->str);
for (i = 1; i < arr->length (); i++)
{
printf (", %s", non_terminals[(*arr)[i]]->str);
}
}
/* Function print_grammar_rule.
*/
void
print_grammar_rule (struct grammar_rule *rule)
{
switch (rule->type)
{
case NT2T:
printf ("%s --> %s", non_terminals[rule->lhs_nt]->str,
terminals[rule->u.terminal]->str);
break;
case NT2NT:
printf ("%s --> %s", non_terminals[rule->lhs_nt]->str,
non_terminals[rule->u.non_terminal]->str);
break;
case NT2OP:
printf ("%s --> ", non_terminals[rule->lhs_nt]->str);
switch (rule->u.rhs_exp.primop.op)
{
case POP_ILV:
printf ("ILV_%d_%s (", rule->u.rhs_exp.primop.division,
type_name[rule->u.rhs_exp.primop.out_type]);
break;
case POP_EXTR:
printf ("EXTR_%d,%d_%s (", rule->u.rhs_exp.primop.division,
rule->u.rhs_exp.primop.opd_selector,
type_name[rule->u.rhs_exp.primop.out_type]);
break;
default:
gcc_assert (0);
}
print_rule_operands (&rule->u.rhs_exp.rhs_nt);
printf (")");
break;
default:
gcc_assert (0);
}
if (rule->spec_idx != -1)
printf (" : [%d::%d]", rule->spec_idx, rule->cost);
}
void
print_grammar_rules_in_comment ()
{
int i,j;
printf ("/*\n");
for (i = 0; i < rules.length (); i++)
{
printf ("\n%d:\t", i);
print_grammar_rule (rules[i]);
}
printf ("*/\n\n");
}
void
print_grammar_rules ()
{
int i,j;
printf ("enum rule_type {NT2T, NT2NT, NT2OP};\n\n");
printf ("struct grammar_rule\n{\n");
printf (" int lhs;\n enum rule_type type;\n int spec_idx;\n");
printf (" union\n {\n");
printf (" int terminal;\n int non_terminal;\n");
printf (" struct\n {\n");
printf (" enum primop_code op;\n int selector;\n");
printf (" int division;\n int out_type;\n");
printf (" vec<int> opd;\n");
printf (" } rhs_exp;\n");
printf (" } u;\n");
printf ("};\n\n");
printf ("vec<struct grammar_rule *> rules = vNULL;\n\n");
printf ("void\ninit_grammar_rules ()\n{\n");
printf (" struct grammar_rule *rule;\n\n");
for (i = 0; i < rules.length (); i++)
{
printf (" rule = (struct grammar_rule *)");
printf (" xcalloc (1, sizeof (struct grammar_rule));\n");
printf (" /* %d: ", i);
print_grammar_rule (rules[i]);
printf (" */\n");
switch (rules[i]->type)
{
case NT2T:
printf (" rule->type = NT2T;\n");
printf (" rule->lhs = UNIF_VECT_NT_%s;\n",
non_terminals[rules[i]->lhs_nt]->str);
printf (" rule->u.terminal = UNIF_VECT_T_%s;\n",
terminals[rules[i]->u.terminal]->str);
break;
case NT2NT:
printf (" rule->type = NT2NT;\n");
printf (" rule->lhs = UNIF_VECT_NT_%s;\n",
non_terminals[rules[i]->lhs_nt]->str);
printf (" rule->u.non_terminal = UNIF_VECT_NT_%s;\n",
non_terminals[rules[i]->u.non_terminal]->str);
break;
case NT2OP:
printf (" rule->type = NT2OP;\n");
printf (" rule->lhs = UNIF_VECT_NT_%s;\n",
non_terminals[rules[i]->lhs_nt]->str);
printf (" rule->u.rhs_exp.op = POP_%s;\n",
tree_code_name[rules[i]->u.rhs_exp.primop.op]);
printf (" rule->u.rhs_exp.selector = %d;\n",
rules[i]->u.rhs_exp.primop.opd_selector);
printf (" rule->u.rhs_exp.division = %d;\n",
rules[i]->u.rhs_exp.primop.division);
printf (" rule->u.rhs_exp.out_type = %d;\n",
rules[i]->u.rhs_exp.primop.out_type);
printf (" rule->u.rhs_exp.opd = vNULL;\n");
for (j = 0; j < rules[i]->u.rhs_exp.rhs_nt.length (); j++)
{
printf (" rule->u.rhs_exp.opd.safe_insert (");
printf (" rule->u.rhs_exp.opd.length (), UNIF_VECT_NT_%s);\n",
non_terminals[rules[i]->u.rhs_exp.rhs_nt[j]]->str);
}
break;
default:
gcc_assert (!"Unknown rule.");
}
printf (" rule->spec_idx = %d;\n", rules[i]->spec_idx);
printf (" rules.safe_insert (rules.length (), rule);\n\n");
}
printf ("}\n\n");
}
void
normalize_costs (struct transition_state *state)
{
int i, delta = 0xfffffff;
for (i = 0; i < state->rule.length (); i++)
{
if (state->rule[i] != -1 && delta > state->cost[i])
delta = state->cost[i];
if (delta == 0)
break;
}
if (delta == 0)
return;
for (i = 0; i < state->rule.length (); i++)
{
if (state->rule[i] != -1)
state->cost[i] = state->cost[i] - delta;
}
}
void
closure (struct transition_state *state)
{
bool changed;
int i, cost;
do {
changed = false;
for (i = 0; i < rules.length (); i++)
{
if (rules[i]->type == NT2NT
&& state->rule[rules[i]->u.non_terminal] != -1)
{
cost = ((rules[i]->cost == -1) ? 0
: rules[i]->cost)
+ state->cost[rules[i]->u.non_terminal];
if (state->rule[rules[i]->lhs_nt] == -1
|| cost < state->cost[rules[i]->lhs_nt])
{
state->rule[rules[i]->lhs_nt] = i;
state->cost[rules[i]->lhs_nt] = cost;
changed = true;
}
}
}
} while (changed == true);
}
void
compute_leaf_states (vec<struct transition_state *> *worklist)
{
int i, j, idx;
for (i = 0; i < terminals.length (); i++)
{
struct transition_state *state = (struct transition_state *)
xcalloc (1, sizeof (struct transition_state));
state->rule.reserve_exact (non_terminals.length ());
state->cost.reserve_exact (non_terminals.length ());
state->nt.reserve_exact (non_terminals.length ());
for (j = 0; j < non_terminals.length (); j++)
{
state->rule.safe_insert (j, -1);
state->cost.safe_insert (j, -1);
state->nt.safe_insert (j, j);
}
for (j = 0; j < rules.length (); j++)
{
if (rules[j]->type == NT2T
&& rules[j]->u.terminal == i)
{
if (rules[j]->spec_idx == -1)
{
state->rule[rules[j]->lhs_nt] = j;
state->cost[rules[j]->lhs_nt] = 0;
}
else if (state->rule[rules[j]->lhs_nt] == -1
|| rules[j]->cost
< state->cost[rules[j]->lhs_nt])
{
state->rule[rules[j]->lhs_nt] = j;
state->cost[rules[j]->lhs_nt]
= rules[j]->cost;
}
}
}
normalize_costs (state);
closure (state);
worklist->safe_push (state);
idx = states.length ();
state->id = idx;
states.safe_insert (idx, state);
terminals[i]->state = idx;
}
}
struct transition_state *
project (enum primop_code pcode, int div, int sel, int type, int idx,
struct transition_state *state)
{
vec<int> ntlist = vNULL;
vec<int> costlist = vNULL;
vec<int> rulelist = vNULL;
int j;
struct transition_state *new_state = (struct transition_state *)
xcalloc (1, sizeof (struct transition_state));
for (j = 0; j < rules.length (); j++)
{
if (rules[j]->type != NT2OP)
continue;
if (rules[j]->u.rhs_exp.primop.op != pcode
|| rules[j]->u.rhs_exp.primop.division != div
|| non_terminals[rules[j]->lhs_nt]->type != type
|| rules[j]->u.rhs_exp.primop.out_type != type)
continue;
if (rules[j]->u.rhs_exp.primop.op == POP_EXTR
&& rules[j]->u.rhs_exp.primop.opd_selector != sel)
continue;
// if (state->cost[rules[j]->u.rhs_exp.rhs_nt[idx]] == -1)
// continue;
ntlist.safe_insert (ntlist.length (), rules[j]->u.rhs_exp.rhs_nt[idx]);
costlist.safe_insert (costlist.length (),
state->cost[rules[j]->u.rhs_exp.rhs_nt[idx]]);
rulelist.safe_insert (rulelist.length (), j);
}
new_state->rule = rulelist.copy ();
new_state->cost = costlist.copy ();
new_state->nt = ntlist.copy ();
new_state->id = -1;
normalize_costs (new_state);
return new_state;
}
bool
increment_next (int idx, int arity, vec<int> *opd_list,
vec<struct transition_state *> rep_states[],
int pstate_idx, int pstate_loc)
{
int i;
if (idx == pstate_loc)
{
(*opd_list)[idx] = pstate_loc;
idx++;
}
if (idx >= arity - 1)
return false;
(*opd_list)[idx] = 0;
if ((*opd_list)[idx + 1] < rep_states[idx + 1].length () - 1)
{
(*opd_list)[idx + 1]++;
return true;
}
return increment_next (idx + 1, arity, opd_list, rep_states,
pstate_idx, pstate_loc);
}
bool
rep_state_combination_next (struct transition_state *proj_state,
vec<struct transition_state *> rep_states[],
int act_arity, int idx, int rep_loc,
vec<int> *opd_list)
{
int i, j;
for (i = 0; i < act_arity; i++)
if (rep_states[i] == vNULL)
return false;
if (*opd_list == vNULL)
{
for (i = 0; i < act_arity; i++)
if (i != idx)
opd_list->safe_insert (i, 0);
else
opd_list->safe_insert (i, rep_loc);
return true;
}
for (i = 0; i < act_arity; i++)
{
if (i == idx)
{
(*opd_list)[i] = rep_loc;
continue;
}
if ((*opd_list)[i] < rep_states[i].length () - 1)
{
(*opd_list)[i]++;
return true;
}
else
{
for (j = 0; j < i; j++)
if (i != idx)
(*opd_list)[j] = 0;
return increment_next (j, act_arity, opd_list,
rep_states, idx, rep_loc);
}
}
return false;
}
bool
is_state_equal_p (struct transition_state *st1, struct transition_state *st2)
{
int i;
if (st1->nt.length () != st2->nt.length ())
return false;
if (st1->rule.length () != st2->rule.length ())
return false;
if (st1->cost.length () != st2->cost.length ())
return false;
for (i = 0; i < st1->nt.length (); i++)
{
if (st1->nt[i] != st2->nt[i]
|| st1->cost[i] != st2->cost[i])
{
return false;
}
}
return true;
}
void
trim_state_table ()
{
}
void
compute_transitions (struct operator_info *op,
struct transition_state *state,
vec<struct transition_state *> *worklist)
{
int i, j, l;
long long k;
int cost;
struct transition_state *proj_state;
struct transition_state *result = (struct transition_state *)
xcalloc (1, sizeof (struct transition_state));
result->rule.reserve_exact (non_terminals.length ());
result->cost.reserve_exact (non_terminals.length ());
result->nt.reserve_exact (non_terminals.length ());
result->id = -1;
for (j = 0; j < non_terminals.length (); j++)
{
result->rule.safe_insert (j, -1);
result->cost.safe_insert (j, -1);
result->nt.safe_insert (j, j);
}
for (i = 0; i < op->act_arity; i++)
{
vec<int> opd_list;
proj_state = project (op->pcode, op->arity, op->sel, op->type, i, state);
for (j = 0; j < op->rep_states[i].length (); j++)
{
if (is_state_equal_p (proj_state, op->rep_states[i][j]))
break;
}
proj_state->id = j;
if (j == op->rep_states[i].length ())
{
op->rep_states[i].safe_insert (j, proj_state);
}
else
continue;
if (op->map[i].length () < state->id)
op->map[i].safe_grow_cleared (state->id, NULL);
op->map[i].safe_insert (state->id, proj_state);
opd_list = vNULL;
for (k = 0; k < op->rep_states[i].length (); k++)
{
if (op->rep_states[i][k]->nt == vNULL)
break;
}
if (k != op->rep_states[i].length ())
continue;
while (rep_state_combination_next (proj_state,
op->rep_states,
op->act_arity,
i,
j,
&opd_list))
{
for(j = 0; j < rules.length (); j++)
{
if (rules[j]->type != NT2OP)
continue;
if (rules[j]->cost == -1)
continue;
if (rules[j]->u.rhs_exp.primop.op != op->pcode)
continue;
if (rules[j]->u.rhs_exp.primop.division != op->arity)
continue;
if (rules[j]->u.rhs_exp.primop.opd_selector != op->sel)
continue;
if (rules[j]->u.rhs_exp.primop.out_type != op->type)
continue;
if (non_terminals[rules[j]->lhs_nt]->type != op->type)
continue;
for (k = 0; k < proj_state->nt.length (); k++)
if (proj_state->nt[k] == rules[j]->u.rhs_exp.rhs_nt[i])
break;
if (k == proj_state->nt.length () || proj_state->cost[k] == -1)
continue;
cost = rules[j]->cost + proj_state->cost[k];
for (k = 0; k < op->act_arity; k++)
{
if (k == i)
continue;
for (l = 0;
l < op->rep_states[k][opd_list[k]]->nt.length ();
l++)
if (op->rep_states[k][opd_list[k]]->nt[l]
== rules[j]->u.rhs_exp.rhs_nt[k])
break;
if (l == op->rep_states[k][opd_list[k]]->nt.length ()
|| op->rep_states[k][opd_list[k]]->cost[l] == -1)
{
cost = -1;
break;
}
else
cost = cost
+ op->rep_states[k][opd_list[k]]->cost[l];
}
if (cost == -1)
continue;
if ((result->cost[rules[j]->lhs_nt] == -1
|| cost < result->cost[rules[j]->lhs_nt]))
{
result->cost.safe_insert (rules[j]->lhs_nt, cost);
result->rule.safe_insert (rules[j]->lhs_nt, j);
result->nt.safe_insert (rules[j]->lhs_nt, rules[j]->lhs_nt);
}
}
normalize_costs (result);
closure (result);
for (k = 0; k < states.length (); k++)
if (is_state_equal_p (result, states[k]))
break;
result->id = k;
if (k == states.length ())
{
states.safe_insert (k, result);
worklist->safe_insert (worklist->length (), result);
}
long long int index = 0;
for (k = op->act_arity - 1; k >= 0; k--)
{
index = (index << 16) | opd_list[k];
}
for (k = 0; k < op->index_map.length (); k++)
if (index == op->index_map[k] /*&& is_state_equal_p (result,
states[op->trans_map[k]])*/)
break;
if (k != op->index_map.length ())
continue;
k = op->index_map.length ();
op->index_map.safe_insert (k, index);
op->trans_map.safe_insert (k, result->id);
op->state_map.safe_insert (k, state->id);
}
}
}
vec<struct operator_info *> op_list = vNULL;
struct operator_info *
create_op (enum primop_code pcode, int arity, int sel, int act_arity, int type)
{
struct operator_info *new_op;
int i;
new_op = (struct operator_info *) xcalloc (1, sizeof (struct operator_info));
new_op->pcode = pcode;
new_op->arity = arity;
new_op->sel = sel;
new_op->type = type;
new_op->act_arity = act_arity;
new_op->index_map = vNULL;
new_op->trans_map = vNULL;
for (i = 0; i < act_arity; i++)
{
new_op->map[i] = vNULL;
new_op->rep_states[i] = vNULL;
}
return new_op;
}
void
create_transition_table ()
{
vec<struct transition_state *> worklist;
int i, j, k;
struct operator_info *op;
states = vNULL;
worklist = vNULL;
compute_leaf_states (&worklist);
for (k = 0; k < type_name.length (); k++)
for (i = 0; i < arity_list.length (); i++)
{
for (j = 0; j < arity_list[i]; j++)
{
op = create_op (POP_EXTR, arity_list[i], j, 1, k);
op_list.safe_insert (op_list.length (), op);
}
op = create_op (POP_ILV, arity_list[i], -1,
arity_list[i], k);
op_list.safe_insert (op_list.length (), op);
}
while (worklist.length () != 0)
{
struct transition_state *state;
state = worklist.pop ();
for (i = 0; i < op_list.length (); i++)
{
compute_transitions (op_list[i], state, &worklist);
}
}
}
void
print_states ()
{
int i, j;
printf ("enum unif_vect_state {\n");
for (i = 0; i < states.length (); i++)
{
printf (" /* state_%d: \n", i);
for (j = 0; j < non_terminals.length (); j++)
{
if (states[i]->rule[j] != -1)
{
printf ("\t");
print_grammar_rule (rules[states[i]->rule[j]]);
printf ("\t\t%d : %d >> %d\n", states[i]->nt[j], states[i]->cost[j], j);
}
/*else if (states[i]->cost[j] != -1)
{
printf ("\t\t%d : %d\n", states[i]->nt[j], states[i]->cost[j]);
}*/
}
printf (" */\n");
printf (" UNIF_VECT_STATE_%d = %d,\n", i, i);
}
printf (" UNIF_VECT_STATE_MAX = %d};\n\n", i);
printf ("int state_nt_to_rule_map[UNIF_VECT_STATE_MAX][UNIF_VECT_NT_MAX];\n");
printf ("void\ninit_state_to_rule_map ()\n{\n");
printf ("memset (state_nt_to_rule_map, -1, %d);\n", states.length () * non_terminals.length ());
for (i = 0; i < states.length (); i++)
{
for (j = 0; j < non_terminals.length (); j++)
{
if (states[i]->rule[j] != -1)
{
printf ("state_nt_to_rule_map[UNIF_VECT_STATE_%d][UNIF_VECT_NT_%s] = %d;\n", i, non_terminals[j]->str, states[i]->rule[j]);
}
}
}
printf ("}\n\n");
}
void
print_rep_state ()
{
int i, j, k, l;
printf ("struct {\n");
for (i = 0; i < op_list.length (); i++)
{
for (j = 0; j < op_list[i]->act_arity; j++)
{
if (op_list[i]->pcode == POP_ILV)
{
printf (" vec<int> nt_%s_%s_%d_%d",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, j);
printf ("[%d];\n", op_list[i]->rep_states[j].length ());
printf (" vec<int> cost_%s_%s_%d_%d",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, j);
printf ("[%d];\n", op_list[i]->rep_states[j].length ());
}
else
{
printf (" vec<int> nt_%s_%s_%d_%d",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, op_list[i]->sel);
printf ("[%d];\n", op_list[i]->rep_states[j].length ());
printf (" vec<int> cost_%s_%s_%d_%d",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, op_list[i]->sel);
printf ("[%d];\n", op_list[i]->rep_states[j].length ());
}
}
}
printf ("} rep_state;\n\n");
printf ("void\ninit_rep_states ()\n{\n");
for (i = 0; i < op_list.length (); i++)
{
for (j = 0; j < op_list[i]->act_arity; j++)
{
for (k = 0; k < op_list[i]->rep_states[j].length (); k++)
{
for (l = 0; l < op_list[i]->rep_states[j][k]->nt.length (); l++)
{
if (op_list[i]->pcode == POP_ILV)
printf (" rep_state.nt_%s_%s_%d_%d",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, j);
else
printf (" rep_state.nt_%s_%s_%d_%d",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, op_list[i]->sel);
printf ("[%d][%d] = UNIF_VECT_NT_%s;\n", k, l,
non_terminals[op_list[i]->rep_states[j][k]->nt[l]]->str);
if (op_list[i]->pcode == POP_ILV)
printf (" rep_state.cost_%s_%s_%d_%d",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, j);
else
printf (" rep_state.cost_%s_%s_%d_%d",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, op_list[i]->sel);
printf ("[%d][%d] = %d;\n", k, l,
op_list[i]->rep_states[j][k]->cost[l]);
}
}
}
}
printf ("}\n\n");
}
void
print_trans_map ()
{
int i, j, k;
long long index;
char str[50], str1[100];
printf ("struct {\n");
for (j = 0; j < op_list.length (); j++)
{
if (op_list[j]->pcode == POP_ILV)
printf (" int %s_%s_%d", tree_code_name[op_list[j]->pcode], type_name[op_list[j]->type],
op_list[j]->arity);
else
printf (" int %s_%s_%d_%d", tree_code_name[op_list[j]->pcode], type_name[op_list[j]->type],
op_list[j]->arity, op_list[j]->sel);
for (k = 0; k < op_list[j]->act_arity; k++)
{
printf ("[1024]");
}
printf (";\n");
}
printf ("} transition;\n\n");
printf ("int parent_state[%d][UNIF_VECT_STATE_MAX];\n\n", op_list.length ());
printf ("void\ninit_transition_table ()\n{\n");
for (j = 0; j < op_list.length (); j++)
{
if (op_list[j]->pcode == POP_ILV)
sprintf (str, " transition.%s_%s_%d", tree_code_name[op_list[j]->pcode], type_name[op_list[j]->type],
op_list[j]->arity);
else
sprintf (str, " transition.%s_%s_%d_%d", tree_code_name[op_list[j]->pcode], type_name[op_list[j]->type],
op_list[j]->arity, op_list[j]->sel);
for (i = 0; i < op_list[j]->index_map.length (); i++)
{
index = op_list[j]->index_map[i];
sprintf (str1, "%s", str);
for (k = 0; k < op_list[j]->act_arity; k++)
{
sprintf (str1, "%s[%lld]", str1, (index & 0x00000000000003ff));
index = index >> 16;
}
//printf ("%s.safe_insert (%s.length (), UNIF_VECT_STATE_%d);\n", str1, str1, op_list[j]->trans_map[i]);
printf ("%s = UNIF_VECT_STATE_%d;\n", str1, op_list[j]->trans_map[i]);
}
}
/* for (j = 0; j < op_list.length (); j++)
{
for (i = 0; i < op_list[j]->index_map.length (); i++)
{
printf ("parent_state[%d][UNIF_VECT_STATE_%d] = UNIF_VECT_STATE_%d;\n", j, op_list[j]->trans_map[i], op_list[j]->state_map[i]);
}
}*/
printf ("}\n\n");
}
void
print_non_terminals ()
{
int i;
printf ("enum unif_vect_nt {\n");
for (i = 0; i < non_terminals.length (); i++)
{
printf (" UNIF_VECT_NT_%s = %d,\n", non_terminals[i]->str, i);
}
printf (" UNIF_VECT_NT_MAX = %d};\n\n", i);
for (i = 0; i < non_terminals.length (); i++)
{
printf ("int get_%s_nonterminal_state ()\n{\n", non_terminals[i]->str);
printf (" return UNIF_VECT_NT_%s;\n", non_terminals[i]->str);
printf ("}\n\n");
}
}
void
print_terminals ()
{
int i;
printf ("enum unif_vect_t {\n");
for (i = 0; i < terminals.length (); i++)
{
printf (" UNIF_VECT_T_%s = %d,\n", terminals[i]->str, i);
}
printf (" UNIF_VECT_T_MAX = %d};\n\n", i);
for (i = 0; i < terminals.length (); i++)
{
printf ("int get_%s_terminal_state ()\n{\n", terminals[i]->str);
printf (" return %d;\n", terminals[i]->state);
printf ("}\n\n");
}
printf ("int get_REG_terminal_state (int type)\n{\n");
printf (" switch (type)\n {\n");
for (i = 0; i < type_name.length (); i++)
{
printf ("case %smode: return get_REG_%s_terminal_state ();\n",type_name[i], type_name[i]);
}
printf (" default:\n gcc_assert (!\"Type not supported\");\n");
printf (" }\n}\n\n");
printf ("int get_CONST_terminal_state (int type)\n{\n");
printf (" switch (type)\n {\n");
for (i = 0; i < type_name.length (); i++)
{
printf ("case %smode: return get_CONST_%s_terminal_state ();\n",type_name[i], type_name[i]);
}
printf (" default:\n gcc_assert (!\"Type not supported\");\n");
printf (" }\n}\n\n");
}
void
print_op_list ()
{
int i;
printf ("enum unif_vect_op_list {\n");
for (i = 0; i < op_list.length (); i++)
if (op_list[i]->pcode == POP_ILV)
printf (" UNIF_VECT_%s_%s_%d,\n", tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity);
else
printf (" UNIF_VECT%s_%s_%d_%d,\n", tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, op_list[i]->sel);
printf (" UNIF_VECT_OP_MAX};\n\n");
}
void
print_map ()
{
int i, j, k;
int max = 0;
printf ("enum map_op_name {\n");
for (i = 0; i < op_list.length (); i++)
{
for (j = 0; j < op_list[i]->act_arity; j++)
{
printf ("MAP_OP_%s_%s_%d_%d,\n", tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity,
op_list[i]->sel == -1 ? j : op_list[i]->sel);
if (max < op_list[i]->map[j].length ())
max = op_list[i]->map[j].length ();
}
}
printf ("MAP_OP_NAME_MAX};\n\n");
printf ("int rep_state_map[MAP_OP_NAME_MAX][%d];\n\n", max);
printf ("void\ninit_rep_state_map ()\n{\n");
for (i = 0; i < op_list.length (); i++)
{
for (j = 0; j < op_list[i]->act_arity; j++)
{
for (k = 0; k < op_list[i]->map[j].length (); k++)
if (op_list[i]->map[j][k] != NULL)
printf ("rep_state_map[MAP_OP_%s_%s_%d_%d][UNIF_VECT_STATE_%d] = %d;\n",
tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type], op_list[i]->arity,
op_list[i]->sel == -1 ? j : op_list[i]->sel, k,
op_list[i]->map[j][k]->id);
//printf ("%d, %d, %d\n", i, j, k);
}
}
printf ("}\n\n");
}
void
print_init_func ()
{
long long int num;
char *str, *str1;
int i, j;
printf ("void\nunif_vect_init_funct ()\n{\n");
str1 = (char *) xcalloc (20, sizeof (char));
str = (char *) xcalloc (40, sizeof (char));
for (i = 0; i < op_list.length (); i++)
{
num = 1;
if (op_list[i]->pcode == POP_ILV)
{
sprintf (str1, "%s_%s_%d", tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity);
}
else
{
sprintf (str1, "%s_%s_%d_%d", tree_code_name[op_list[i]->pcode], type_name[op_list[i]->type],
op_list[i]->arity, op_list[i]->sel);
}
sprintf (str, "%s", str1);
for (j = 0; j < op_list[i]->act_arity; j++)
{
num = num * 1024;
}
printf (" memset (transition.%s, -1, %d * sizeof (int));\n", str1, num);
}
printf (" memset (rep_state_map, -1, sizeof (rep_state_map));\n");
printf (" init_transition_table ();\n");
printf (" init_rep_state_map ();\n");
printf (" init_state_to_rule_map (); \n");
printf (" init_grammar_rules ();\n");
printf (" init_nt_2_rule_map ();\n}\n\n");
}
void
print_state_fn_for_ilv ()
{
int i, j;
char *str = (char *) xcalloc (100, sizeof (char));
printf ("int\ntransition_state_for_ilv");
printf (" (int act_arity, vec<int> state_idx, int type)\n{\n");
for (i = 0; i < op_list.length (); i++)
{
if (op_list[i]->pcode == POP_ILV)
{
printf (" if (act_arity == %d && type == %smode)\n {\n", op_list[i]->arity, type_name[op_list[i]->type]);
sprintf (str, "");
for (j = 0; j < op_list[i]->act_arity; j++)
{
printf ("\tif (rep_state_map[MAP_OP_ILV_%s_%d_%d]",
type_name[op_list[i]->type], op_list[i]->arity, j);
printf ("[state_idx[%d]] == -1)\n", j);
printf ("\t return -1;\/\/get_REG_terminal_state ();\n");
sprintf (str,
"%s\n\t[rep_state_map[MAP_OP_ILV_%s_%d_%d][state_idx[%d]]]",
str, type_name[op_list[i]->type], op_list[i]->arity, j, j);
}
printf (" return transition.ILV_%s_%d%s", type_name[op_list[i]->type], op_list[i]->arity, str);
printf (";\n }\n");
}
}
printf ("}\n\n");
}
void
print_state_fn_for_extr ()
{
int i;
printf ("int\ntransition_state_for_extr");
printf (" (int act_arity, int sel, int state_idx, int type)\n{\n");
for (i = 0; i < op_list.length (); i++)
{
if (op_list[i]->pcode == POP_EXTR)
{
printf (" if (act_arity == %d && sel == %d && type == %smode)\n {\n",
op_list[i]->arity,
op_list[i]->sel, type_name[op_list[i]->type]);
printf (" if (rep_state_map[MAP_OP_EXTR_%s_%d_%d]",
type_name[op_list[i]->type], op_list[i]->arity, op_list[i]->sel);
printf ("[state_idx] == -1)\n");
printf ("\treturn -1;\/\/get_REG_terminal_state ();\n");
printf (" return transition.EXTR_%s_%d_%d\n", type_name[op_list[i]->type], op_list[i]->arity,
op_list[i]->sel);
printf ("\t [rep_state_map[MAP_OP_EXTR_%s_%d_%d][state_idx]];\n }\n", type_name[op_list[i]->type],
op_list[i]->arity, op_list[i]->sel);
}
}
printf ("}\n\n");
}
void
print_permute_order_fn ()
{
printf ("struct vec_perm_order_spec target_spec[] = TARGET_VEC_PERM_CONST_ORDER;\n");
printf ("void\nprint_permute_order (int ruleno)\n{\n");
printf (" printf (\"\\n\");\n");
printf (" if (rules[ruleno]->spec_idx != -1)\n {\n");
printf (" for (int i = 0; i < target_spec[rules[ruleno]->spec_idx].out_vec_size; i++)\n");
printf ("\t{\n");
printf ("\t printf (\"%%d \", target_spec[rules[ruleno]->spec_idx].perm_order[i]);\n");
printf ("\t}\n");
printf (" printf (\"\\n\");\n");
printf (" }\n");
printf ("}\n\n");
}
void
print_get_rule_no_fn ()
{
printf ("/* Each entry holds list of rules which result in the non-terminal. */\n");
printf ("vec<int> nt_2_rule_rel[UNIF_VECT_NT_MAX];\n\n");
printf ("void\ninit_nt_2_rule_map ()\n{");
printf (" int i, j;\n");
printf (" for (i = 0; i < UNIF_VECT_NT_MAX; i++)\n {\n");
printf (" nt_2_rule_rel[i] = vNULL;");
printf (" }\n");
printf (" for (i = 0; i < rules.length (); i++)\n {\n");
printf (" nt_2_rule_rel[rules[i]->lhs].safe_insert (nt_2_rule_rel[rules[i]->lhs].length (), i);\n");
printf (" }\n");
printf ("}\n\n");
printf ("int\nget_rule_number (struct primop_tree *ptree, int nt)\n{\n");
printf (" return state_nt_to_rule_map[PT_AUX(ptree)][nt];");
printf ("}\n\n");
}
void
print_get_child_nt_fn ()
{
printf ("bool is_NT2T_rule (int ruleno)\n{\n");
printf (" return (rules[ruleno]->type == NT2T);\n");
printf ("}\n\n");
printf ("int\nget_child_nt (int state, int ruleno, int nt_idx)\n{\n");
printf (" if (rules[ruleno]->type == NT2OP)\n");
printf (" return rules[ruleno]->u.rhs_exp.opd[nt_idx];\n");
printf (" if (rules[ruleno]->type == NT2NT)\n {\n");
printf (" return get_child_nt (state, state_nt_to_rule_map[state][rules[ruleno]->u.non_terminal], nt_idx);\n }\n");
printf (" if (rules[ruleno]->type == NT2T)\n");
printf (" gcc_assert (0);\n");
printf ("}\n\n");
}
void
print_transition_table ()
{
print_op_list ();
print_non_terminals ();
print_terminals ();
print_states ();
print_grammar_rules ();
print_trans_map ();
print_map ();
print_get_rule_no_fn ();
print_get_child_nt_fn ();
print_init_func ();
print_state_fn_for_ilv ();
print_state_fn_for_extr ();
print_permute_order_fn ();
}
int main (int argc, const char **argv)
{
printf ("/* Generated automatically by the program `genvect-inst-tiles'\n\
from the macro TARGET_VEC_PERM_CONST_ORDER in target header file. */\n\n");
printf ("#include \"config.h\"\n");
printf ("#include \"system.h\"\n");
printf ("#include \"coretypes.h\"\n");
printf ("#include \"backend.h\"\n");
printf ("#include \"tree.h\"\n");
printf ("#include \"gimple.h\"\n");
printf ("#include \"predict.h\"\n");
printf ("#include \"tree-pass.h\"\n");
printf ("#include \"ssa.h\"\n");
printf ("#include \"cgraph.h\"\n");
printf ("#include \"fold-const.h\"\n");
printf ("#include \"stor-layout.h\"\n");
printf ("#include \"gimple-iterator.h\"\n");
printf ("#include \"gimple-walk.h\"\n");
printf ("#include \"tree-ssa-loop-manip.h\"\n");
printf ("#include \"tree-cfg.h\"\n");
printf ("#include \"cfgloop.h\"\n");
printf ("#include \"tree-vectorizer.h\"\n");
printf ("#include \"tree-ssa-propagate.h\"\n");
printf ("#include \"dbgcnt.h\"\n");
printf ("#include \"tree-scalar-evolution.h\"\n");
printf ("#include \"tree-vect-unified.h\"\n");
printf ("#include \"tree-pretty-print.h\"\n");
printf ("#include \"gimple-pretty-print.h\"\n");
printf ("#include \"target.h\"\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"tm_p.h\"\n");
printf ("#include \"optabs-tree.h\"\n");
printf ("#include \"dumpfile.h\"\n");
printf ("#include \"alias.h\"\n");
printf ("#include \"tree-eh.h\"\n");
printf ("#include \"gimplify.h\"\n");
printf ("#include \"gimplify-me.h\"\n");
printf ("#include \"tree-ssa-loop-ivopts.h\"\n");
printf ("#include \"tree-ssa-loop.h\"\n");
printf ("#include \"expr.h\"\n");
printf ("#include \"builtins.h\"\n");
printf ("#include \"params.h\"\n");
printf ("#include \"pretty-print.h\"\n");
printf ("\n");
create_instruction_tiles ();
print_instruction_tiles ();
create_grammar_rules ();
print_grammar_rules_in_comment ();
create_transition_table ();
print_transition_table ();
}