Commit 9ebabcf3 authored by Matthias Braun's avatar Matthias Braun
Browse files

refactoring of returns_twice=>no_coalescing rule

This mainly adds comments explaining the situation and avoids an extra
graph walk.
parent 4e36e86b
......@@ -186,7 +186,7 @@ static void amd64_finish_graph(ir_graph *irg)
/* create and coalesce frame entities */
irg_walk_graph(irg, NULL, amd64_collect_frame_entity_nodes, fec_env);
be_assign_entities(fec_env, amd64_set_frame_entity, at_begin, true);
be_assign_entities(fec_env, amd64_set_frame_entity, at_begin);
be_free_frame_entity_coalescer(fec_env);
irg_block_walk_graph(irg, NULL, amd64_after_ra_walker, NULL);
......
......@@ -220,7 +220,7 @@ static void arm_emit(ir_graph *irg)
be_fec_env_t *fec_env = be_new_frame_entity_coalescer(irg);
irg_walk_graph(irg, NULL, arm_collect_frame_entity_nodes, fec_env);
be_assign_entities(fec_env, arm_set_frame_entity, at_begin, true);
be_assign_entities(fec_env, arm_set_frame_entity, at_begin);
be_free_frame_entity_coalescer(fec_env);
irg_block_walk_graph(irg, NULL, arm_after_ra_walker, NULL);
......
......@@ -60,6 +60,7 @@ struct be_fec_env_t {
set_frame_entity_func set_frame_entity;
bool at_begin; /**< frame entities should be allocate at
the beginning of the stackframe */
bool coalescing_forbidden;
};
/** Compare 2 affinity edges (used in quicksort) */
......@@ -673,10 +674,14 @@ void be_free_frame_entity_coalescer(be_fec_env_t *env)
free(env);
}
void be_forbid_coalescing(be_fec_env_t *env)
{
env->coalescing_forbidden = true;
}
void be_assign_entities(be_fec_env_t *env,
set_frame_entity_func set_frame_entity,
bool alloc_entities_at_begin,
bool coalescing_allowed)
bool alloc_entities_at_begin)
{
env->set_frame_entity = set_frame_entity;
env->at_begin = alloc_entities_at_begin;
......@@ -685,7 +690,7 @@ void be_assign_entities(be_fec_env_t *env,
stat_ev_dbl("spillslots", ARR_LEN(env->spills));
}
if (be_coalesce_spill_slots && coalescing_allowed) {
if (be_coalesce_spill_slots && !env->coalescing_forbidden) {
do_greedy_coalescing(env);
}
......
......@@ -26,6 +26,11 @@ be_fec_env_t *be_new_frame_entity_coalescer(ir_graph *irg);
*/
void be_free_frame_entity_coalescer(be_fec_env_t *env);
/**
* forbid coalescing of spillslots.
*/
void be_forbid_coalescing(be_fec_env_t *env);
/**
* Adds a node that needs a frame entity and consumes memory (Reload nodes). The
* memory edges are followed to find memory-phis and the entities that produce
......@@ -46,6 +51,6 @@ typedef void (*set_frame_entity_func)(ir_node *node, ir_entity *entity);
* Adds memory perms where needed.
*/
void be_assign_entities(be_fec_env_t *env, set_frame_entity_func set_frame,
bool alloc_entities_at_begin, bool coalescing_allowed);
bool alloc_entities_at_begin);
#endif
......@@ -811,6 +811,17 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data)
const ir_mode *mode;
int align;
/* Disable coalescing for "returns twice" calls: In case of setjmp/longjmp
* our control flow graph isn't completely correct: There are no backedges
* from longjmp to the setjmp => coalescing would produce wrong results. */
if (is_ia32_Call(node)) {
const ia32_call_attr_t *attrs = get_ia32_call_attr_const(node);
const ir_type *type = attrs->call_tp;
mtp_additional_properties mtp = get_method_additional_properties(type);
if (mtp & mtp_property_returns_twice)
be_forbid_coalescing(env);
}
if (be_is_Reload(node) && be_get_frame_entity(node) == NULL) {
mode = get_spill_mode_mode(get_irn_mode(node));
align = get_mode_size_bytes(mode);
......@@ -873,20 +884,6 @@ need_stackent:
be_node_needs_frame_entity(env, node, mode, align);
}
static void ia32_check_coal_allowed(ir_node *irn, void *data)
{
bool *allowed = (bool*)data;
if (!*allowed || !is_ia32_Call(irn))
return;
const ia32_call_attr_t *attrs = get_ia32_call_attr_const(irn);
const ir_type *type = attrs->call_tp;
mtp_additional_properties mtp = get_method_additional_properties(type);
if (mtp & mtp_property_returns_twice)
*allowed = false;
}
static int determine_ebp_input(ir_node *ret)
{
const arch_register_t *bp = &ia32_registers[REG_EBP];
......@@ -1035,13 +1032,11 @@ static void ia32_emit(ir_graph *irg)
ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg);
bool at_begin = stack_layout->sp_relative ? true : false;
bool coal_allowed = true;
be_fec_env_t *fec_env = be_new_frame_entity_coalescer(irg);
/* create and coalesce frame entities */
irg_walk_graph(irg, NULL, ia32_collect_frame_entity_nodes, fec_env);
irg_walk_graph(irg, NULL, ia32_check_coal_allowed, &coal_allowed);
be_assign_entities(fec_env, ia32_set_frame_entity, at_begin, coal_allowed);
be_assign_entities(fec_env, ia32_set_frame_entity, at_begin);
be_free_frame_entity_coalescer(fec_env);
irg_block_walk_graph(irg, NULL, ia32_after_ra_walker, NULL);
......
......@@ -682,7 +682,19 @@ static void register_peephole_optimisation(ir_op *op, peephole_opt_func func)
static void sparc_collect_frame_entity_nodes(ir_node *node, void *data)
{
be_fec_env_t *env = (be_fec_env_t*)data;
be_fec_env_t *env = (be_fec_env_t*)data;
/* Disable coalescing for "returns twice" calls: In case of setjmp/longjmp
* our control flow graph isn't completely correct: There are no backedges
* from longjmp to the setjmp => coalescing would produce wrong results. */
if (is_sparc_Call(node)) {
const sparc_call_attr_t *attrs = get_sparc_call_attr_const(node);
const ir_type *type = attrs->call_type;
mtp_additional_properties mtp = get_method_additional_properties(type);
if (mtp & mtp_property_returns_twice)
be_forbid_coalescing(env);
return;
}
if (be_is_Reload(node) && be_get_frame_entity(node) == NULL) {
ir_mode *mode = get_irn_mode(node);
......@@ -738,30 +750,14 @@ static void fix_constraints_walker(ir_node *block, void *env)
}
}
static void sparc_check_coal_allowed(ir_node *irn, void *data)
{
bool *allowed = (bool*)data;
if (!*allowed || !is_sparc_Call(irn))
return;
const sparc_call_attr_t *attrs = get_sparc_call_attr_const(irn);
const ir_type *type = attrs->call_type;
mtp_additional_properties mtp = get_method_additional_properties(type);
if (mtp & mtp_property_returns_twice)
*allowed = false;
}
void sparc_finish_graph(ir_graph *irg)
{
be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg);
bool at_begin = stack_layout->sp_relative ? true : false;
bool coal_allowed = true;
be_fec_env_t *fec_env = be_new_frame_entity_coalescer(irg);
irg_walk_graph(irg, NULL, sparc_collect_frame_entity_nodes, fec_env);
irg_walk_graph(irg, NULL, sparc_check_coal_allowed, &coal_allowed);
be_assign_entities(fec_env, sparc_set_frame_entity, at_begin, coal_allowed);
be_assign_entities(fec_env, sparc_set_frame_entity, at_begin);
be_free_frame_entity_coalescer(fec_env);
sparc_adjust_stack_entity_offsets(irg);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment