}
/* Set the ARM machine node attributes to default values. */
-static void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** in_reqs,
- const arch_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units,
+void init_arm_attributes(ir_node *node, int flags,
+ const arch_register_req_t ** in_reqs,
+ const arch_register_req_t ** out_reqs,
+ const be_execution_unit_t ***execution_units,
int n_res, unsigned latency) {
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
arm_attr_t *attr = get_arm_attr(node);
+ (void) execution_units;
+ (void) latency;
attr->in_req = in_reqs;
attr->out_req = out_reqs;
}
static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b) {
+ (void) a;
+ (void) b;
/* never identical */
return 1;
}
static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b) {
+ (void) a;
+ (void) b;
/* never identical */
return 1;
}
ir_node *irn;
sched_foreach(bl, irn) {
+ int ofs;
/*
Check, if the node relates to an entity on the stack frame.
DBG((env->dbg, LEVEL_2, "%F has offset %d (including bias %d)\n", ent, offset, bias));
}
- /*
- If the node modifies the stack pointer by a constant offset,
- record that in the bias.
- */
- if(arch_irn_is(arch_env, irn, modify_sp)) {
- int ofs = arch_get_sp_bias(arch_env, irn);
+ if(omit_fp) {
+ /*
+ * If the node modifies the stack pointer by a constant offset,
+ * record that in the bias.
+ */
+ ofs = arch_get_sp_bias(arch_env, irn);
if(be_is_IncSP(irn)) {
if(ofs == BE_STACK_FRAME_SIZE_EXPAND) {
}
}
- if(omit_fp)
- bias += ofs;
+ bias += ofs;
}
}
return -1;
}
-static int appel_dump_clique(appel_clique_walker_t *env, pset *live, ir_node *bl, int curr_nr, int start_nr)
+static int appel_dump_clique(appel_clique_walker_t *env, const ir_nodeset_t *live, ir_node *bl, int curr_nr, int start_nr)
{
ir_node **live_arr = alloca(env->co->cls->n_regs * sizeof(live_arr[0]));
ir_node *irn;
int n_live;
int j;
+ ir_nodeset_iterator_t iter;
n_live = 0;
- foreach_pset(live, irn)
+ foreach_ir_nodeset(live, irn, iter)
live_arr[n_live++] = irn;
/* dump the live after clique */
appel_block_info_t *bli = phase_get_or_set_irn_data(&env->ph, bl);
struct obstack *obst = &env->obst;
void *base = obstack_base(obst);
- pset *live = pset_new_ptr_default();
+ ir_nodeset_t live;
+ ir_nodeset_iterator_t iter;
be_lv_t *lv = env->co->cenv->birg->lv;
int n_insns = 0;
}
DBG((dbg, LEVEL_2, "%+F\n", bl));
- be_liveness_end_of_block(lv, env->co->aenv, env->co->cls, bl, live);
+ ir_nodeset_init(&live);
+ be_liveness_end_of_block(lv, env->co->aenv, env->co->cls, bl, &live);
/* Generate the bad and ugly. */
for(i = n_insns - 1; i >= 0; --i) {
/* The first live set has to be saved in the block border set. */
if(i == n_insns - 1) {
j = 0;
- foreach_pset(live, irn) {
+ foreach_ir_nodeset(&live, irn, iter) {
bli->live_end[j] = irn;
bli->live_end_nr[j] = curr_nr + j;
++j;
ir_node *op = insn->ops[j].carrier;
bitset_t *adm = insn->ops[j].regs;
int k;
- int nr;
+ size_t nr;
if(!insn->ops[j].has_constraints)
continue;
nr = 0;
- foreach_pset(live, irn) {
+ foreach_ir_nodeset(&live, irn, iter) {
if(irn == op) {
- pset_break(live);
break;
}
++nr;
}
- assert(nr < pset_count(live));
+ assert(nr < ir_nodeset_size(&live));
for(k = 0; k < env->co->cls->n_regs; ++k) {
int mapped_col = env->color_map[k];
}
/* dump the clique and update the stuff. */
- curr_nr = appel_dump_clique(env, live, bl, curr_nr, start_nr);
+ curr_nr = appel_dump_clique(env, &live, bl, curr_nr, start_nr);
/* remove all defs. */
for(j = 0; j < insn->use_start; ++j)
- pset_remove_ptr(live, insn->ops[j].carrier);
+ ir_nodeset_remove(&live, insn->ops[j].carrier);
if(is_Phi(insn->irn) && arch_irn_consider_in_reg_alloc(env->co->aenv, env->co->cls, insn->irn)) {
bli->phi[bli->n_phi] = insn->irn;
/* add all uses */
else
for(j = insn->use_start; j < insn->n_ops; ++j)
- pset_insert_ptr(live, insn->ops[j].carrier);
+ ir_nodeset_insert(&live, insn->ops[j].carrier);
}
/* print the start clique. */
- curr_nr = appel_dump_clique(env, live, bl, curr_nr, start_nr);
+ curr_nr = appel_dump_clique(env, &live, bl, curr_nr, start_nr);
i = 0;
- foreach_pset(live, irn) {
+ foreach_ir_nodeset(&live, irn, iter) {
bli->live_in[i] = irn;
bli->live_in_nr[i] = PTR_TO_INT(get_irn_link(irn));
++i;
}
bli->n_live_in = i;
- del_pset(live);
+ ir_nodeset_destroy(&live);
free(insns);
obstack_free(obst, base);
env->curr_nr = curr_nr;
be_lv_t *lv = birg->lv;
ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_graph *irg = get_irn_irg(bl);
- pset *live = pset_new_ptr_default();
+ ir_nodeset_t live;
+ ir_nodeset_iterator_t iter;
ir_node *curr, *irn, *perm, **nodes;
- int i, n;
+ size_t i, n;
DBG((dbg, LEVEL_1, "Insert Perm after: %+F\n", pos));
- be_liveness_nodes_live_at(lv, arch_env, cls, pos, live);
-
- n = pset_count(live);
+ ir_nodeset_init(&live);
+ be_liveness_nodes_live_at(lv, arch_env, cls, pos, &live);
+ n = ir_nodeset_size(&live);
if(n == 0) {
- del_pset(live);
+ ir_nodeset_destroy(&live);
return NULL;
}
nodes = xmalloc(n * sizeof(nodes[0]));
DBG((dbg, LEVEL_1, "live:\n"));
- for(irn = pset_first(live), i = 0; irn; irn = pset_next(live), i++) {
+ i = 0;
+ foreach_ir_nodeset(&live, irn, iter) {
DBG((dbg, LEVEL_1, "\t%+F\n", irn));
nodes[i] = irn;
+ i++;
}
- del_pset(live);
+ ir_nodeset_destroy(&live);
perm = be_new_Perm(cls, irg, bl, n, nodes);
sched_add_after(pos, perm);
return !problem_found;
}
-pset *be_liveness_transfer(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *irn, pset *live)
-{
- int i, n;
-
- /* You should better break out of your loop when hitting the first phi function. */
- assert(!is_Phi(irn) && "liveness_transfer produces invalid results for phi nodes");
-
-#ifndef SCHEDULE_PROJS
- /* kill all Proj's if a node is killed */
- if (get_irn_mode(irn) == mode_T) {
- const ir_edge_t *edge;
-
- foreach_out_edge(irn, edge) {
- ir_node *proj = get_edge_src_irn(edge);
-
- if (arch_irn_consider_in_reg_alloc(arch_env, cls, proj)) {
- ir_node *del = pset_remove_ptr(live, proj);
- (void) del;
- assert(proj == del);
- }
- }
- }
-#endif
-
- if (arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
- ir_node *del = pset_remove_ptr(live, irn);
- (void) del;
- assert(irn == del);
- }
-
- for (i = 0, n = get_irn_arity(irn); i < n; ++i) {
- ir_node *op = get_irn_n(irn, i);
-
- if (arch_irn_consider_in_reg_alloc(arch_env, cls, op))
- pset_insert_ptr(live, op);
- }
-
- return live;
-}
-
-void be_liveness_transfer_ir_nodeset(const arch_env_t *arch_env,
- const arch_register_class_t *cls,
- ir_node *node, ir_nodeset_t *nodeset)
+void be_liveness_transfer(const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ ir_node *node, ir_nodeset_t *nodeset)
{
int i, arity;
-pset *be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *bl, pset *live)
-{
- int i;
- assert(lv->nodes && "live sets must be computed");
- be_lv_foreach(lv, bl, be_lv_state_end, i) {
- ir_node *irn = be_lv_get_irn(lv, bl, i);
- if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn))
- pset_insert_ptr(live, irn);
- }
-
- return live;
-}
-
-void be_liveness_end_of_block_ir_nodeset(const be_lv_t *lv,
- const arch_env_t *arch_env,
- const arch_register_class_t *cls,
- const ir_node *block,
- ir_nodeset_t *live)
+void be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ const ir_node *block, ir_nodeset_t *live)
{
int i;
-pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
+void be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ const ir_node *pos, ir_nodeset_t *live)
{
const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_node *irn;
* exit immediately, so that this node is still live
*/
if(irn == pos)
- return live;
+ return;
be_liveness_transfer(arch_env, cls, irn, live);
}
-
- return live;
}
-pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
+void be_liveness_nodes_live_at_input(const be_lv_t *lv,
+ const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ const ir_node *pos, ir_nodeset_t *live)
{
const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_node *irn;
sched_foreach_reverse(bl, irn) {
be_liveness_transfer(arch_env, cls, irn, live);
if(irn == pos)
- return live;
+ return;
}
-
- return live;
}
static void collect_node(ir_node *irn, void *data)
* the nodes live after irn.
* @return live.
*/
-pset *be_liveness_transfer(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *irn, pset *live);
-
-void be_liveness_transfer_ir_nodeset(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *node, ir_nodeset_t *nodeset);
+void be_liveness_transfer(const arch_env_t *arch_env,
+ const arch_register_class_t *cls, ir_node *node,
+ ir_nodeset_t *nodeset);
/**
* Put all node live at the end of a block into a set.
* @param live The set to put them into.
* @return live.
*/
-pset *be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *bl, pset *live);
-
-void be_liveness_end_of_block_ir_nodeset(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *bl, ir_nodeset_t *nodeset);
+void be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ const ir_node *bl, ir_nodeset_t *nodeset);
/**
* Compute a set of nodes which are live at another node.
* @param cls The register class to consider.
* @param pos The node.
* @param live The set to put them into.
- * @return live.
*/
-pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live);
+void be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ const ir_node *pos, ir_nodeset_t *live);
/**
* Compute a set of nodes which are live at another node.
* @param cls The register class to consider.
* @param pos The node.
* @param live The set to put them into.
- * @return live.
*/
-pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live);
+void be_liveness_nodes_live_at_input(const be_lv_t *lv,
+ const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ const ir_node *pos, ir_nodeset_t *live);
/**
* Make sure the live sets are computed.
const be_irg_t *birg = loop_ana->birg;
const arch_env_t *aenv = be_get_birg_arch_env(birg);
be_lv_t *lv = be_get_birg_liveness(birg);
- pset *live_nodes = pset_new_ptr_default();
+ ir_nodeset_t live_nodes;
ir_node *irn;
int max_live;
DBG((dbg, LEVEL_1, "Processing Block %+F\n", block));
/* determine largest pressure with this block */
- live_nodes = be_liveness_end_of_block(lv, aenv, cls, block, live_nodes);
- max_live = pset_count(live_nodes);
+ ir_nodeset_init(&live_nodes);
+ be_liveness_end_of_block(lv, aenv, cls, block, &live_nodes);
+ max_live = ir_nodeset_size(&live_nodes);
sched_foreach_reverse(block, irn) {
int cnt;
if (is_Phi(irn))
break;
- live_nodes = be_liveness_transfer(aenv, cls, irn, live_nodes);
- cnt = pset_count(live_nodes);
+ be_liveness_transfer(aenv, cls, irn, &live_nodes);
+ cnt = ir_nodeset_size(&live_nodes);
max_live = MAX(cnt, max_live);
}
DBG((dbg, LEVEL_1, "Finished with Block %+F (%s %u)\n", block, cls->name, max_live));
- del_pset(live_nodes);
+ ir_nodeset_destroy(&live_nodes);
return max_live;
}
static void lower_nodes_after_ra_walker(ir_node *irn, void *walk_env) {
if (! is_Block(irn) && ! is_Proj(irn)) {
if (be_is_Perm(irn)) {
- int perm_stayed = 1; //push_through_perm(irn, walk_env);
+ int perm_stayed = push_through_perm(irn, walk_env);
if (perm_stayed)
lower_perm_node(irn, walk_env);
}
unsigned max_height; /**< maximum height in the current block */
rss_opts_t *opts; /**< The options */
be_lv_t *liveness; /**< The liveness information for this irg */
- pset *live_block; /**< Values alive at end of block */
+ ir_nodeset_t live_block; /**< Values alive at end of block */
const arch_register_class_t *cls; /**< The current register class */
DEBUG_ONLY(firm_dbg_module_t *dbg);
} rss_t;
DBG((rss->dbg, LEVEL_1, "register class %s\n", arch_register_class_name(cls)));
/* Get all live value at end of Block having current register class */
- rss->live_block = pset_new_ptr(10);
- be_liveness_end_of_block(rss->liveness, rss->arch_env, rss->cls, rss->block, rss->live_block);
+ ir_nodeset_init(&rss->live_block);
+ be_liveness_end_of_block(rss->liveness, rss->arch_env, rss->cls, rss->block, &rss->live_block);
/* reset the list of interesting nodes */
plist_clear(rss->nodes);
*/
perform_value_serialization_heuristic(rss);
- del_pset(rss->live_block);
+ ir_nodeset_destroy(&rss->live_block);
}
phase_free(&rss->ph);
DBG((dbg, LEVEL_1, "spilling block %+F\n", block));
ir_nodeset_init(&live_nodes);
- be_liveness_end_of_block_ir_nodeset(lv, arch_env, cls, block, &live_nodes);
+ be_liveness_end_of_block(lv, arch_env, cls, block, &live_nodes);
foreach_ir_nodeset(&live_nodes, node, iter) {
DBG((dbg, LEVEL_2, "\t%+F is live-end... ", node));
ir_node *node;
int max_pressure;
int loop_unused_spills_needed;
- pset *live_nodes = pset_new_ptr_default();
+ ir_nodeset_t live_nodes;
const be_lv_t *lv = env->lv;
- be_liveness_end_of_block(lv, env->arch, env->cls, block, live_nodes);
- max_pressure = pset_count(live_nodes);
+ ir_nodeset_init(&live_nodes);
+
+ be_liveness_end_of_block(lv, env->arch, env->cls, block, &live_nodes);
+ max_pressure = ir_nodeset_size(&live_nodes);
DBG((dbg, DBG_LIVE, "Reduce pressure to %d In Block %+F:\n", env->registers_available, block));
if(is_Phi(node))
break;
- be_liveness_transfer(env->arch, env->cls, node, live_nodes);
- pressure = pset_count(live_nodes);
+ be_liveness_transfer(env->arch, env->cls, node, &live_nodes);
+ pressure = ir_nodeset_size(&live_nodes);
if(pressure > max_pressure)
max_pressure = pressure;
}
- del_pset(live_nodes);
+ ir_nodeset_destroy(&live_nodes);
loop_unused_spills_needed = max_pressure - env->registers_available;
for (i = 0; i < n; i++) {
const arch_register_class_t *cls = arch_isa_get_reg_class(aenv->isa, i);
- ir_node *irn;
- pset *live_nodes = pset_new_ptr(64);
- int max_live;
+ ir_node *irn;
+ ir_nodeset_t live_nodes;
+ int max_live;
- live_nodes = be_liveness_end_of_block(env->lv, aenv, cls, block, live_nodes);
- max_live = pset_count(live_nodes);
+ ir_nodeset_init(&live_nodes);
+ be_liveness_end_of_block(env->lv, aenv, cls, block, &live_nodes);
+ max_live = ir_nodeset_size(&live_nodes);
sched_foreach_reverse(block, irn) {
int cnt;
if(is_Phi(irn))
break;
- live_nodes = be_liveness_transfer(aenv, cls, irn, live_nodes);
- cnt = pset_count(live_nodes);
+ be_liveness_transfer(aenv, cls, irn, &live_nodes);
+ cnt = ir_nodeset_size(&live_nodes);
max_live = cnt < max_live ? max_live : cnt;
}
stat_be_block_regpressure(irg, block, max_live, cls->name);
+ ir_nodeset_destroy(&live_nodes);
}
}
/**
* Print all nodes of a pset into a file.
*/
-static void print_living_values(FILE *F, pset *live_nodes) {
+static void print_living_values(FILE *F, const ir_nodeset_t *live_nodes) {
+ ir_nodeset_iterator_t iter;
ir_node *node;
ir_fprintf(F, "\t");
- foreach_pset(live_nodes, node) {
+ foreach_ir_nodeset(live_nodes, node, iter) {
ir_fprintf(F, "%+F ", node);
}
ir_fprintf(F, "\n");
*/
static void verify_liveness_walker(ir_node *block, void *data) {
be_verify_register_pressure_env_t *env = (be_verify_register_pressure_env_t *)data;
- pset *live_nodes = pset_new_ptr_default();
+ ir_nodeset_t live_nodes;
ir_node *irn;
int pressure;
/* collect register pressure info, start with end of a block */
- be_liveness_end_of_block(env->lv, env->arch_env, env->cls, block, live_nodes);
+ ir_nodeset_init(&live_nodes);
+ be_liveness_end_of_block(env->lv, env->arch_env, env->cls, block,
+ &live_nodes);
- pressure = pset_count(live_nodes);
+ pressure = ir_nodeset_size(&live_nodes);
if(pressure > env->registers_available) {
ir_fprintf(stderr, "Verify Warning: Register pressure too high at end of block %+F(%s) (%d/%d):\n",
block, get_irg_dump_name(env->irg), pressure, env->registers_available);
- print_living_values(stderr, live_nodes);
+ print_living_values(stderr, &live_nodes);
env->problem_found = 1;
}
if (is_Phi(irn))
break;
- be_liveness_transfer(env->arch_env, env->cls, irn, live_nodes);
+ be_liveness_transfer(env->arch_env, env->cls, irn, &live_nodes);
- pressure = pset_count(live_nodes);
+ pressure = ir_nodeset_size(&live_nodes);
if(pressure > env->registers_available) {
ir_fprintf(stderr, "Verify Warning: Register pressure too high before node %+F in %+F(%s) (%d/%d):\n",
irn, block, get_irg_dump_name(env->irg), pressure, env->registers_available);
- print_living_values(stderr, live_nodes);
+ print_living_values(stderr, &live_nodes);
env->problem_found = 1;
}
}
- del_pset(live_nodes);
+ ir_nodeset_destroy(&live_nodes);
}
/**
int problem_found;
} be_verify_register_allocation_env_t;
-static void check_register_constraints(ir_node *node, be_verify_register_allocation_env_t *env) {
+static void check_register_constraints(ir_node *node,
+ be_verify_register_allocation_env_t *env)
+{
const arch_env_t *arch_env = env->arch_env;
const arch_register_t *reg;
int i, arity;
}
static void check_register_allocation(be_verify_register_allocation_env_t *env,
- const arch_register_class_t *regclass, pset *nodes) {
+ const arch_register_class_t *regclass,
+ ir_nodeset_t *nodes)
+{
const arch_env_t *arch_env = env->arch_env;
const arch_register_t *reg = NULL;
int fail = 0;
bitset_t *registers = bitset_alloca(arch_register_class_n_regs(regclass));
ir_node *node;
+ ir_nodeset_iterator_t iter;
- foreach_pset(nodes, node) {
+ foreach_ir_nodeset(nodes, node, iter) {
if (arch_get_irn_reg_class(arch_env, node, -1) != regclass)
continue;
continue;
if (bitset_is_set(registers, reg->index)) {
- pset_break(nodes);
fail = 1;
break;
}
reg->name, get_nodes_block(node), get_irg_dump_name(env->irg));
env->problem_found = 1;
- foreach_pset(nodes, node) {
+ foreach_ir_nodeset(nodes, node, iter) {
if (arch_get_irn_register(arch_env, node) == reg) {
ir_fprintf(stderr, " at node %+F\n", node);
}
for (i = 0; i < nregclasses; ++i) {
const arch_register_class_t *regclass = arch_isa_get_reg_class(isa, i);
ir_node *node;
- pset *live_nodes = pset_new_ptr_default();
+ ir_nodeset_t live_nodes;
+
+ ir_nodeset_init(&live_nodes);
- be_liveness_end_of_block(env->lv, env->arch_env, regclass, block, live_nodes);
- check_register_allocation(env, regclass, live_nodes);
+ be_liveness_end_of_block(env->lv, env->arch_env, regclass, block,
+ &live_nodes);
+ check_register_allocation(env, regclass, &live_nodes);
sched_foreach_reverse(block, node) {
if (is_Phi(node))
break;
- be_liveness_transfer(env->arch_env, regclass, node, live_nodes);
- check_register_allocation(env, regclass, live_nodes);
+ be_liveness_transfer(env->arch_env, regclass, node, &live_nodes);
+ check_register_allocation(env, regclass, &live_nodes);
check_register_constraints(node, env);
}
- del_pset(live_nodes);
+ ir_nodeset_destroy(&live_nodes);
}
}
}
}
-static int ia32_get_sp_bias(const void *self, const ir_node *irn) {
+static int ia32_get_sp_bias(const void *self, const ir_node *node)
+{
(void) self;
- if(is_Proj(irn)) {
- long proj = get_Proj_proj(irn);
- ir_node *pred = get_Proj_pred(irn);
- if (is_ia32_Push(pred) && proj == pn_ia32_Push_stack)
- return 4;
- if (is_ia32_Pop(pred) && proj == pn_ia32_Pop_stack)
- return -4;
- }
+ if (is_ia32_Push(node))
+ return 4;
+
+ if (is_ia32_Pop(node))
+ return -4;
return 0;
}
/* in case of address mode operations add additional cycles */
else if (op_tp == ia32_AddrModeD || op_tp == ia32_AddrModeS) {
/*
- In case of stack access add 5 cycles (we assume stack is in cache),
- other memory operations cost 20 cycles.
+ In case of stack access and access to fixed addresses add 5 cycles
+ (we assume they are in cache), other memory operations cost 20
+ cycles.
*/
- cost += is_ia32_use_frame(irn) ? 5 : 20;
+ if(is_ia32_use_frame(irn) ||
+ (is_ia32_NoReg_GP(get_irn_n(irn, 0)) &&
+ is_ia32_NoReg_GP(get_irn_n(irn, 1)))) {
+ cost += 5;
+ } else {
+ cost += 20;
+ }
}
return cost;
return pop;
}
-static ir_node* create_spproj(ia32_code_gen_t *cg, ir_node *node, ir_node *pred, int pos, ir_node *schedpoint) {
+static ir_node* create_spproj(ia32_code_gen_t *cg, ir_node *node, ir_node *pred, int pos) {
ir_graph *irg = get_irn_irg(node);
dbg_info *dbg = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
sp = new_rd_Proj(dbg, irg, block, pred, spmode, pos);
arch_set_irn_register(cg->arch_env, sp, spreg);
-#ifdef SCHEDULE_PROJS
- sched_add_before(schedpoint, sp);
-#endif
return sp;
}
assert( (entbits == 32 || entbits == 64) && "spillslot on x86 should be 32 or 64 bit");
push = create_push(cg, node, node, sp, mem, inent);
- sp = create_spproj(cg, node, push, pn_ia32_Push_stack, node);
+ sp = create_spproj(cg, node, push, pn_ia32_Push_stack);
if(entbits == 64) {
// add another push after the first one
push = create_push(cg, node, node, sp, mem, inent);
add_ia32_am_offs_int(push, 4);
- sp = create_spproj(cg, node, push, pn_ia32_Push_stack, node);
+ sp = create_spproj(cg, node, push, pn_ia32_Push_stack);
}
set_irn_n(node, i, new_Bad());
assert( (entbits == 32 || entbits == 64) && "spillslot on x86 should be 32 or 64 bit");
pop = create_pop(cg, node, node, sp, outent);
- sp = create_spproj(cg, node, pop, pn_ia32_Pop_stack, node);
+ sp = create_spproj(cg, node, pop, pn_ia32_Pop_stack);
if(entbits == 64) {
add_ia32_am_offs_int(pop, 4);
// add another pop after the first one
pop = create_pop(cg, node, node, sp, outent);
- sp = create_spproj(cg, node, pop, pn_ia32_Pop_stack, node);
+ sp = create_spproj(cg, node, pop, pn_ia32_Pop_stack);
}
pops[i] = pop;
},
# Load / Store
+#
+# Note that we add additional latency values depending on address mode, so a
+# lateny of 0 for load is correct
Load => {
op_flags => "L|F",
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
- latency => 3,
+ latency => 0,
emit => ". mov%SE%ME%.l %AM, %D0",
outs => [ "res", "M" ],
units => [ "GP" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
emit => '. mov%M %binop',
- latency => 3,
+ latency => 2,
units => [ "GP" ],
mode => "mode_M",
},
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => ["none" ] },
emit => '. mov%M %binop',
- latency => 3,
+ latency => 2,
units => [ "GP" ],
mode => "mode_M",
},
emit => '. push%M %unop2',
ins => [ "base", "index", "val", "stack", "mem" ],
outs => [ "stack:I|S", "M" ],
- latency => 3,
+ latency => 2,
units => [ "GP" ],
modified_flags => [],
},
emit => '. pop%M %DAM1',
outs => [ "stack:I|S", "res", "M" ],
ins => [ "base", "index", "stack", "mem" ],
- latency => 4,
+ latency => 3, # Pop is more expensive than Push on Athlon
units => [ "GP" ],
modified_flags => [],
},
set_ia32_op_type(load, ia32_AddrModeS);
set_ia32_am_flavour(load, ia32_am_N);
set_ia32_am_sc(load, floatent);
- res = new_r_Proj(irg, block, load, mode_vfp, pn_ia32_vfld_res);
+ set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
+ res = new_r_Proj(irg, block, load, mode_vfp, pn_ia32_vfld_res);
}
set_ia32_ls_mode(load, mode);
} else {
set_ia32_am_flavour(load, ia32_am_N);
set_ia32_am_sc(load, floatent);
set_ia32_ls_mode(load, mode);
+ set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
res = new_r_Proj(irg, block, load, mode_xmm, pn_ia32_xLoad_res);
}
}
static
-int check_immediate_constraint(tarval *tv, char immediate_constraint_type)
+int check_immediate_constraint(long val, char immediate_constraint_type)
{
- long val;
-
- assert(tarval_is_long(tv));
- val = get_tarval_long(tv);
-
switch (immediate_constraint_type) {
case 0:
return 1;
}
if(cnst != NULL) {
+ long val;
+
offset = get_Const_tarval(cnst);
- if(!tarval_is_long(offset)) {
+ if(tarval_is_long(offset)) {
+ val = get_tarval_long(offset);
+ } else if(tarval_is_null(offset)) {
+ val = 0;
+ } else {
ir_fprintf(stderr, "Optimisation Warning: tarval from %+F is not a "
"long?\n", cnst);
return NULL;
}
- if(!check_immediate_constraint(offset, immediate_constraint_type))
+ if(!check_immediate_constraint(val, immediate_constraint_type))
return NULL;
}
if(symconst != NULL) {
set_ia32_op_type(new_op, ia32_AddrModeS);
set_ia32_am_flavour(new_op, ia32_am_B);
set_ia32_ls_mode(new_op, mode);
+ set_ia32_flags(new_op, get_ia32_flags(new_op) | arch_irn_flags_rematerializable);
SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));