}
/* assume worst case: all remaining pairs build a cycle or chain */
- cycle->elems = calloc((n - n_pairs_done) * 2, sizeof(cycle->elems[0]));
+ cycle->elems = xcalloc((n - n_pairs_done) * 2, sizeof(cycle->elems[0]));
cycle->n_elems = 2; /* initial number of elements is 2 */
cycle->elems[0] = pairs[start].in_reg;
cycle->elems[1] = pairs[start].out_reg;
/* go to the first not-checked pair */
while (pairs[i].checked) i++;
- cycle = calloc(1, sizeof(*cycle));
+ cycle = xcalloc(1, sizeof(*cycle));
cycle = get_perm_cycle(cycle, pairs, n, i);
DB((mod, LEVEL_1, "%+F: following %s created:\n ", irn, cycle->type == PERM_CHAIN ? "chain" : "cycle"));
//TODO: - iff PERM_CYCLE && do_copy -> determine free temp reg and insert copy to/from it before/after
// the copy cascade (this reduces the cycle into a chain)
- /* build copy/swap nodes */
- for (i = 0; i < cycle->n_elems - 1; i++) {
+ /* build copy/swap nodes from back to front */
+ for (i = cycle->n_elems - 2; i >= 0; i--) {
arg1 = get_node_for_register(pairs, n, cycle->elems[i], 0);
arg2 = get_node_for_register(pairs, n, cycle->elems[i + 1], 0);
in[0] = arg1;
in[1] = arg2;
+ /* At this point we have to handle the following problem: */
+ /* */
+ /* If we have a cycle with more than two elements, then */
+ /* this could correspond to the following Perm node: */
+ /* */
+ /* +----+ +----+ +----+ */
+ /* | r1 | | r2 | | r3 | */
+ /* +-+--+ +-+--+ +--+-+ */
+ /* | | | */
+ /* | | | */
+ /* +-+--------+---------+-+ */
+ /* | Perm | */
+ /* +-+--------+---------+-+ */
+ /* | | | */
+ /* | | | */
+ /* +-+--+ +-+--+ +--+-+ */
+ /* |Proj| |Proj| |Proj| */
+ /* | r2 | | r3 | | r1 | */
+ /* +----+ +----+ +----+ */
+ /* */
+ /* This node is about to be split up into two 2x Perm's */
+ /* for which we need 4 Proj's and the one additional Proj */
+ /* of the first Perm has to be one IN of the second. So in */
+ /* general we need to create one additional Proj for each */
+ /* "middle" Perm and set this to one in node of the successor */
+ /* Perm. */
+
DBG((mod, LEVEL_1, "%+F creating exchange node (%+F, %s) and (%+F, %s) with\n",
irn, arg1, cycle->elems[i]->name, arg2, cycle->elems[i + 1]->name));
DBG((mod, LEVEL_1, "%+F (%+F, %s) and (%+F, %s)\n",
cpyxchg = be_new_Perm(reg_class, env->chord_env->irg, block, 2, in);
+ if (i > 0) {
+ /* cycle is not done yet */
+ int pidx = get_pairidx_for_regidx(pairs, n, cycle->elems[i]->index, 0);
+
+ /* create intermediate proj */
+ res2 = new_r_Proj(get_irn_irg(irn), block, cpyxchg, get_irn_mode(res1), 0);
+
+ /* set as in for next Perm */
+ pairs[pidx].in_node = res2;
+ }
+ else {
+ sched_remove(res2);
+ }
+
sched_remove(res1);
- sched_remove(res2);
set_Proj_pred(res2, cpyxchg);
set_Proj_proj(res2, 0);
/* insert the copy/exchange node in schedule after the magic schedule node (see above) */
sched_add_after(sched_point, cpyxchg);
+ /* set the new scheduling point */
+ sched_point = cpyxchg;
DBG((mod, LEVEL_1, "replacing %+F with %+F, placed new node after %+F\n", irn, cpyxchg, sched_point));
}
- free(cycle->elems);
+ free((void *) cycle->elems);
free(cycle);
}
set_size += arch_register_class_n_regs(reg_class);
}
- in_keep = malloc(set_size * sizeof(ir_node *));
+ in_keep = xmalloc(set_size * sizeof(ir_node *));
proj_set = bitset_malloc(set_size);
bitset_clear_all(proj_set);
reg = arch_register_for_index(reg_class, j);
/* only check caller save registers */
- if (arch_register_type_is(reg, caller_saved)) {
+ if (arch_register_type_is(reg, caller_save)) {
/* Only create new proj, iff not already present */
if (!bitset_is_set(proj_set, bitset_idx)) {
* @param irn The node to be checked for lowering
* @param walk_env The walker environment
*/
-static void lower_nodes_before_sched_walker(ir_node *irn, const void *walk_env) {
+static void lower_nodes_before_sched_walker(ir_node *irn, void *walk_env) {
const arch_env_t *arch_env = walk_env;
if (!is_Block(irn) && !is_Proj(irn)) {