#include "irgwalk.h"
#include "irtools.h"
#include "return.h"
+#include "xmalloc.h"
// debug
#include "irdump.h"
static ir_node* walk_to_projx(ir_node* start)
{
ir_node* pred;
- ir_node* cdep;
pred = get_nodes_block(start);
- cdep = get_unique_cdep(pred);
- if (cdep == NULL) return NULL;
- assert(get_irn_arity(pred) == 1);
+ /* if there are multiple control flow predecessors nothing sensible can be
+ * done */
+ if (get_irn_arity(pred) > 1) return NULL;
+
pred = get_irn_n(pred, 0);
if (get_irn_op(pred) == op_Proj) {
assert(get_irn_mode(pred) == mode_X);
int evil;
} block_info;
+#define get_block_blockinfo(block) ((block_info*)get_irn_link(block))
static int can_empty_block(ir_node* block)
{
- return !((block_info*)get_irn_link(block))->evil;
+ return !get_block_blockinfo(block)->evil;
}
-/*
+/**
* Copies the DAG starting at node to the ith predecessor block of src_block
* -if the node isn't in the src_block, this is a nop and the node is returned
* -if the node is a phi in the src_block, the ith predecessor of the phi is
}
-/*
+/**
* Duplicate and move the contents of ith block predecessor into its
* predecessors if the block has multiple control dependencies and only one
* successor.
pred_arity = get_irn_arity(pred_block);
arity = get_irn_arity(block);
info = get_irn_link(block);
- ins = malloc(sizeof(*ins) * (arity + pred_arity - 1));
+ ins = xmalloc(sizeof(*ins) * (arity + pred_arity - 1));
for (phi = info->phi; phi != NULL; phi = get_irn_link(phi)) {
for (j = 0; j < i; ++j) ins[j] = get_irn_n(phi, j);
for (j = 0; j < pred_arity; ++j) {
for (j = 0; j < pred_arity; ++j) ins[i + j] = get_irn_n(pred_block, j);
for (j = i + 1; j < arity; ++j) ins[pred_arity - 1 + j] = get_irn_n(block, j);
set_irn_in(block, arity + pred_arity - 1, ins);
- free(ins);
+ xfree(ins);
/* Kill all Phis in the fissioned block
* This is to make sure they're not kept alive
}
+/**
+ * Remove predecessors i and j from node and add predecessor new_pred
+ */
+static void rewire(ir_node* node, int i, int j, ir_node* new_pred)
+{
+ int arity = get_irn_arity(node);
+ ir_node** ins = xmalloc(sizeof(*ins) * (arity - 1));
+ int k;
+ int l;
+
+ l = 0;
+ for (k = 0; k < i; ++k) ins[l++] = get_irn_n(node, k);
+ for (++k; k < j; ++k) ins[l++] = get_irn_n(node, k);
+ for (++k; k < arity; ++k) ins[l++] = get_irn_n(node, k);
+ ins[l++] = new_pred;
+ assert(l == arity - 1);
+ set_irn_in(node, l, ins);
+
+ xfree(ins);
+}
+
+
static void if_conv_walker(ir_node* block, void* env)
{
ir_node* phi;
int i;
// Bail out, if there are no Phis at all
- if (((block_info*)get_irn_link(block))->phi == NULL) return;
+ if (get_block_blockinfo(block)->phi == NULL) return;
restart:
arity = get_irn_arity(block);
conds[0] = get_Cond_selector(cond);
psi_block = get_nodes_block(cond);
- phi = ((block_info*)get_irn_link(block))->phi;
+ phi = get_block_blockinfo(block)->phi;
do {
// Don't generate PsiMs
if (get_irn_mode(phi) == mode_M) {
psi = get_irn_n(phi, i);
ir_fprintf(stderr, "Handling memory Phi %+F\n", phi);
} else {
- if (get_Proj_proj(projx0) == pn_Cond_true) {
- vals[0] = get_irn_n(phi, i);
- vals[1] = get_irn_n(phi, j);
+ ir_node* val_i = get_irn_n(phi, i);
+ ir_node* val_j = get_irn_n(phi, j);
+
+ if (val_i == val_j) {
+ psi = val_i;
+ ir_fprintf(stderr, "Generating no psi, because both values are equal\n");
} else {
- vals[0] = get_irn_n(phi, j);
- vals[1] = get_irn_n(phi, i);
+ if (get_Proj_proj(projx0) == pn_Cond_true) {
+ vals[0] = val_i;
+ vals[1] = val_j;
+ } else {
+ vals[0] = val_j;
+ vals[1] = val_i;
+ }
+ psi = new_r_Psi(
+ current_ir_graph, psi_block, 1, conds, vals, get_irn_mode(phi)
+ );
+ ir_fprintf(stderr, "Generating %+F for %+F\n", psi, phi);
}
- psi = new_r_Psi(
- current_ir_graph, psi_block, 1, conds, vals, get_irn_mode(phi)
- );
- ir_fprintf(stderr, "Generating %+F for %+F\n", psi, phi);
}
if (arity == 2) {
exchange(phi, psi);
} else {
- ir_node** ins = malloc(sizeof(*ins) * (arity - 1));
- int k;
- int l;
-
- l = 0;
- for (k = 0; k < i; ++k) ins[l++] = get_irn_n(phi, k);
- for (++k; k < j; ++k) ins[l++] = get_irn_n(phi, k);
- for (++k; k < arity; ++k) ins[l++] = get_irn_n(phi, k);
- ins[l++] = psi;
- assert(l == arity - 1);
- set_irn_in(phi, l, ins);
-
- free(ins);
+ rewire(phi, i, j, psi);
}
phi = get_irn_link(phi);
- } while (phi != NULL && get_irn_op(phi) == op_Phi);
+ } while (phi != NULL);
exchange(get_nodes_block(get_irn_n(block, i)), psi_block);
exchange(get_nodes_block(get_irn_n(block, j)), psi_block);
if (arity == 2) {
ir_fprintf(stderr, "Welding block %+F to %+F\n", block, psi_block);
- ((block_info*)get_irn_link(psi_block))->evil |=
- ((block_info*)get_irn_link(block))->evil;
+ get_block_blockinfo(psi_block)->evil |= get_block_blockinfo(block)->evil;
exchange(block, psi_block);
return;
} else {
- ir_node** ins = malloc(sizeof(*ins) * (arity - 1));
- int k;
- int l;
-
- l = 0;
- for (k = 0; k < i; ++k) ins[l++] = get_irn_n(block, k);
- for (++k; k < j; ++k) ins[l++] = get_irn_n(block, k);
- for (++k; k < arity; ++k) ins[l++] = get_irn_n(block, k);
- ins[l++] = new_r_Jmp(current_ir_graph, psi_block);
- assert(l == arity - 1);
- set_irn_in(block, l, ins);
-
- free(ins);
+ rewire(block, i, j, new_r_Jmp(current_ir_graph, psi_block));
goto restart;
}
}
static void init_block_link(ir_node* block, void* env)
{
- block_info* bi = malloc(sizeof(*bi));
+ block_info* bi = xmalloc(sizeof(*bi));
bi->phi = NULL;
bi->evil = 0;
if (arity == new_arity) return psi; // no attached Psis found
ir_fprintf(stderr, "Folding %+F from %d to %d conds\n", psi, arity, new_arity);
- conds = malloc(new_arity * sizeof(*conds));
- vals = malloc((new_arity + 1) * sizeof(*vals));
+ conds = xmalloc(new_arity * sizeof(*conds));
+ vals = xmalloc((new_arity + 1) * sizeof(*vals));
j = 0;
for (i = 0; i < arity; ++i) {
ir_node* c = get_Psi_cond(psi, i);
);
ir_fprintf(stderr, "Folded %+F into new %+F\n", psi, new_psi);
exchange(psi, new_psi);
- free(vals);
- free(conds);
+ xfree(vals);
+ xfree(conds);
return new_psi;
}
return;
}
- conds = malloc(sizeof(*conds) * new_arity);
- vals = malloc(sizeof(*vals) * (new_arity + 1));
+ conds = xmalloc(sizeof(*conds) * new_arity);
+ vals = xmalloc(sizeof(*vals) * (new_arity + 1));
cond = get_Psi_cond(psi, 0);
val = get_Psi_val(psi, 0);
j = 0;
irg_walk_graph(irg, collect_phis, NULL, NULL);
irg_block_walk_graph(irg, NULL, if_conv_walker, NULL);
+ local_optimize_graph(irg);
dump_ir_block_graph(irg, "_02_ifconv");
- local_optimize_graph(irg);
irg_walk_graph(irg, NULL, optimise_psis, NULL);
dump_ir_block_graph(irg, "_03_postifconv");
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
+#ifdef HAVE_xmalloc_H
+#include <xmalloc.h>
#endif
#include "irgraph_t.h"
/*
* Add this cond info to the list of all cond infos
- * in this graph. This is just done to free the
+ * in this graph. This is just done to xfree the
* set easier afterwards (we save an irg_walk_graph).
*/
list_add(&cwi->cond_info_head, &ci->list);
normalize_one_return(irg);
/* Ensure, that the dominators are computed. */
- compute_doms(irg);
+ assure_doms(irg);
DBG((dbg, LEVEL_1, "if conversion for irg %s(%p)\n",
get_entity_name(get_irg_entity(irg)), irg));