#include "ircons.h"
#include "debug.h"
-#include "irhooks.h"
#include "xmalloc.h"
#include "irnodeset.h"
#include "irnodemap.h"
} perm_cycle_t;
/** returns the number register pairs marked as checked. */
-static int get_n_checked_pairs(reg_pair_t *pairs, int n) {
- int i, n_checked = 0;
+static int get_n_unchecked_pairs(reg_pair_t const *const pairs, int const n)
+{
+ int n_unchecked = 0;
+ int i;
for (i = 0; i < n; i++) {
- if (pairs[i].checked)
- n_checked++;
+ if (!pairs[i].checked)
+ n_unchecked++;
}
- return n_checked;
+ return n_unchecked;
}
/**
{
int head = pairs[start].in_reg->index;
int cur_idx = pairs[start].out_reg->index;
- int const n_pairs_done = get_n_checked_pairs(pairs, n);
+ int const n_pairs_todo = get_n_unchecked_pairs(pairs, n);
perm_type_t cycle_tp = PERM_CYCLE;
int idx;
}
/* assume worst case: all remaining pairs build a cycle or chain */
- cycle->elems = XMALLOCNZ(const arch_register_t*, (n - n_pairs_done) * 2);
+ cycle->elems = XMALLOCNZ(const arch_register_t*, n_pairs_todo * 2);
cycle->n_elems = 2; /* initial number of elements is 2 */
cycle->elems[0] = pairs[start].in_reg;
cycle->elems[1] = pairs[start].out_reg;
const arch_register_class_t *const reg_class = arch_get_irn_register(get_irn_n(irn, 0))->reg_class;
ir_graph *const irg = get_irn_irg(irn);
ir_node *const block = get_nodes_block(irn);
- int const n = get_irn_arity(irn);
- reg_pair_t *const pairs = alloca(n * sizeof(pairs[0]));
+ int const arity = get_irn_arity(irn);
+ reg_pair_t *const pairs = ALLOCAN(reg_pair_t, arity);
int keep_perm = 0;
int do_copy = env->do_copy;
/* Get the schedule predecessor node to the perm.
* nodes after this node, everything should be ok. */
ir_node * sched_point = sched_prev(irn);
const ir_edge_t * edge;
+ const ir_edge_t * next;
+ int n;
int i;
DBG((dbg, LEVEL_1, "perm: %+F, sched point is %+F\n", irn, sched_point));
assert(sched_point && "Perm is not scheduled or has no predecessor");
- assert(n == get_irn_n_edges(irn) && "perm's in and out numbers different");
+ assert(arity == get_irn_n_edges(irn) && "perm's in and out numbers different");
/* build the list of register pairs (in, out) */
- i = 0;
- foreach_out_edge(irn, edge) {
- reg_pair_t *const pair = &pairs[i++];
- ir_node *const out = get_edge_src_irn(edge);
- long const pn = get_Proj_proj(out);
- ir_node *const in = get_irn_n(irn, pn);
+ n = 0;
+ foreach_out_edge_safe(irn, edge, next) {
+ ir_node *const out = get_edge_src_irn(edge);
+ long const pn = get_Proj_proj(out);
+ ir_node *const in = get_irn_n(irn, pn);
+ arch_register_t const *const in_reg = arch_get_irn_register(in);
+ arch_register_t const *const out_reg = arch_get_irn_register(out);
+ reg_pair_t * pair;
+
+ if (in_reg == out_reg) {
+ DBG((dbg, LEVEL_1, "%+F removing equal perm register pair (%+F, %+F, %s)\n",
+ irn, in, out, out_reg->name));
+ exchange(out, in);
+ continue;
+ }
+ pair = &pairs[n++];
pair->in_node = in;
pair->in_reg = arch_get_irn_register(in);
pair->out_node = out;
pair->checked = 0;
}
- /* Mark all equal pairs as checked, and exchange the OUT proj with the IN
- * node. */
- for (i = 0; i < n; i++) {
- reg_pair_t *const pair = &pairs[i];
-
- if (pair->in_reg->index != pair->out_reg->index)
- continue;
-
- DBG((dbg, LEVEL_1, "%+F removing equal perm register pair (%+F, %+F, %s)\n",
- irn, pair->in_node, pair->out_node, pair->out_reg->name));
-
- /* reroute the edges from the proj to the argument */
- exchange(pair->out_node, pair->in_node);
-
- pair->checked = 1;
- }
+ DBG((dbg, LEVEL_1, "%+F has %d unresolved constraints\n", irn, n));
/* Set do_copy to 0 if it's on but we have no free register */
/* TODO check for free register */
}
/* check for cycles and chains */
- while (get_n_checked_pairs(pairs, n) < n) {
+ while (get_n_unchecked_pairs(pairs, n) > 0) {
perm_cycle_t cycle;
int j;
}
DB((dbg, LEVEL_1, "\n"));
- if (n == 2 && cycle.type == PERM_CYCLE) {
+ if (cycle.type == PERM_CYCLE && arity == 2) {
/* We don't need to do anything if we have a Perm with two elements
* which represents a cycle, because those nodes already represent
* exchange nodes */
ir_node *keep, *cpy;
op_copy_assoc_t *entry;
- if (arch_irn_is(other_different, ignore) ||
+ if (arch_irn_is_ignore(other_different) ||
!mode_is_datab(get_irn_mode(other_different))) {
DBG((dbg_constr, LEVEL_1, "ignore constraint for %+F because other_irn is ignore or not a datab node\n", irn));
return;
irg = be_get_birg_irg(env->birg);
op_set = &env->op_set;
block = get_nodes_block(irn);
- cls = arch_get_irn_reg_class(other_different, -1);
+ cls = arch_get_irn_reg_class_out(other_different);
/* Make a not spillable copy of the different node */
/* this is needed because the different irn could be */
cpy = find_copy(skip_Proj(irn), other_different);
if (! cpy) {
cpy = be_new_Copy(cls, irg, block, other_different);
- be_node_set_flags(cpy, BE_OUT_POS(0), arch_irn_flags_dont_spill);
+ arch_irn_set_flags(cpy, arch_irn_flags_dont_spill);
DBG((dbg_constr, LEVEL_1, "created non-spillable %+F for value %+F\n", cpy, other_different));
} else {
DBG((dbg_constr, LEVEL_1, "using already existing %+F for value %+F\n", cpy, other_different));
/* of the other_different irn in case of CopyKeep. */
if (has_irn_users(other_different)) {
keep = be_new_CopyKeep_single(cls, irg, block, cpy, irn, get_irn_mode(other_different));
- be_node_set_reg_class(keep, 1, cls);
+ be_node_set_reg_class_in(keep, 1, cls);
} else {
ir_node *in[2];
* @param env the constraint environment
*/
static void assure_different_constraints(ir_node *irn, ir_node *skipped_irn, constraint_env_t *env) {
- const arch_register_req_t *req = arch_get_register_req(irn, -1);
+ const arch_register_req_t *req = arch_get_register_req_out(irn);
if (arch_register_req_is(req, must_be_different)) {
const unsigned other = req->other_different;
/* set register class for all kept inputs */
for (j = 1; j <= n_melt; ++j)
- be_node_set_reg_class(new_ck, j, entry->cls);
+ be_node_set_reg_class_in(new_ck, j, entry->cls);
ir_nodeset_insert(&entry->copies, new_ck);
void assure_constraints(be_irg_t *birg) {
ir_graph *irg = be_get_birg_irg(birg);
constraint_env_t cenv;
- ir_node **nodes;
ir_nodemap_iterator_t map_iter;
ir_nodemap_entry_t map_entry;
/* for all */
foreach_ir_nodemap(&cenv.op_set, map_entry, map_iter) {
- op_copy_assoc_t *entry = map_entry.data;
- int n;
- ir_node *cp;
- ir_nodeset_iterator_t iter;
+ op_copy_assoc_t *entry = map_entry.data;
+ int n = ir_nodeset_size(&entry->copies);
+ ir_node **nodes = ALLOCAN(ir_node*, n);
+ ir_node *cp;
+ ir_nodeset_iterator_t iter;
be_ssa_construction_env_t senv;
- n = ir_nodeset_size(&entry->copies);
- nodes = alloca(n * sizeof(nodes[0]));
-
/* put the node in an array */
DBG((dbg_constr, LEVEL_1, "introduce copies for %+F ", map_entry.node));
/* so we transform unnecessary ones into Keeps. */
foreach_ir_nodeset(&entry->copies, cp, iter) {
if (be_is_CopyKeep(cp) && get_irn_n_edges(cp) < 1) {
- ir_node *keep;
- int n = get_irn_arity(cp);
+ const arch_register_class_t *cls = arch_get_irn_reg_class_out(cp);
+ int n = get_irn_arity(cp);
+ ir_node *keep;
- keep = be_new_Keep(arch_get_irn_reg_class(cp, -1),
- irg, get_nodes_block(cp), n, get_irn_in(cp) + 1);
+ keep = be_new_Keep(cls, irg, get_nodes_block(cp), n, get_irn_in(cp) + 1);
sched_add_before(cp, keep);
/* Set all ins (including the block) of the CopyKeep BAD to keep the verifier happy. */
int n_moved;
int new_size;
ir_node *frontier = bl;
-
+ ir_node *irn;
int i, n;
- const ir_edge_t *edge;
- ir_node *one_proj = NULL, *irn;
- const arch_register_class_t *cls = NULL;
-
- DBG((dbg_permmove, LEVEL_1, "perm move %+F irg %+F\n", perm, irg));
/* get some Proj and find out the register class of that Proj. */
- edge = get_irn_out_edge_first_kind(perm, EDGE_KIND_NORMAL);
- one_proj = get_edge_src_irn(edge);
+ const ir_edge_t *edge = get_irn_out_edge_first_kind(perm, EDGE_KIND_NORMAL);
+ ir_node *one_proj = get_edge_src_irn(edge);
+ const arch_register_class_t *cls = arch_get_irn_reg_class_out(one_proj);
assert(is_Proj(one_proj));
- cls = arch_get_irn_reg_class(one_proj, -1);
+
+ DBG((dbg_permmove, LEVEL_1, "perm move %+F irg %+F\n", perm, irg));
/* Find the point in the schedule after which the
* potentially movable nodes must be defined.
break;
if (arch_irn_is(node, modify_flags))
break;
- if (is_Proj(node)) {
- req = arch_get_register_req(get_Proj_pred(node),
- -1 - get_Proj_proj(node));
- } else {
- req = arch_get_register_req(node, -1);
- }
+ req = arch_get_register_req_out(node);
if (req->type != arch_register_req_type_normal)
break;
for (i = get_irn_arity(node) - 1; i >= 0; --i) {
new_size = arity - n_moved;
if(new_size == 0) {
+ sched_remove(perm);
+ kill_node(perm);
return 0;
}
- map = alloca(new_size * sizeof(map[0]));
- proj_map = alloca(arity * sizeof(proj_map[0]));
+ map = ALLOCAN(int, new_size);
+ proj_map = ALLOCAN(int, arity);
memset(proj_map, -1, sizeof(proj_map[0]));
n = 0;
for (i = 0; i < arity; ++i) {