Commit ee44e331 authored by Michael Beck's avatar Michael Beck
Browse files

- fixed handling of outer frame access

[r25277]
parent a63ae972
......@@ -20,19 +20,21 @@
/**
* @file
* @brief read/write analyze of graph argument, which have mode reference.
* @author Beyhan Veliev
* @author Beyhan Veliev, Michael Beck
* @version $Id$
*/
#include "config.h"
#include <stdlib.h>
#include "adt/raw_bitset.h"
#include "irouts.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "array_t.h"
#include "irprog.h"
#include "entity_t.h"
#include "irgwalk.h"
#include "analyze_irg_args.h"
......@@ -493,6 +495,110 @@ unsigned get_method_param_weight(ir_entity *ent, int pos)
return null_weight;
}
typedef struct walk_env {
unsigned *marks; /**< raw bitset for nodes that could be analysed */
unsigned *param_mask; /**< raw bitset of constant parameters */
unsigned mask_len; /**< length of the parameter bitmask */
unsigned weight; /**< the accumulated weight */
} walk_env;
/**
* Walker, evaluates possible constant folding
*/
static void evaluate_weight(ir_node *irn, void *ctx) {
walk_env *env = ctx;
int i, n;
ir_node *ptr;
if (is_arg_Proj(irn)) {
unsigned argnum = (unsigned)get_Proj_proj(irn);
if (argnum < env->mask_len) {
if (rbitset_is_set(env->param_mask, argnum)) {
/* is a constant parameter */
rbitset_set(env->marks, get_irn_idx(irn));
}
}
return;
}
if (is_irn_constlike(irn)) {
/* is a constant by itself */
rbitset_set(env->marks, get_irn_idx(irn));
return;
}
if (is_Block(irn))
return;
/* handle some special cases */
switch (get_irn_opcode(irn)) {
case iro_Div:
case iro_Quot:
case iro_Mod:
case iro_DivMod:
/* skip the memory input of these nodes */
assert(pn_Generic_M_regular == 0);
n = 1;
break;
case iro_Call:
ptr = get_Call_ptr(irn);
if (! is_SymConst(ptr) && rbitset_is_set(env->marks, get_irn_idx(ptr))) {
/* the arguments is used as an pointer input for a call,
we can probably change an indirect Call into a direct one. */
env->weight += indirect_call_weight;
}
n = 2;
break;
default:
n = 0;
break;
}
for (i = get_irn_arity(irn) - 1; i >= n; --i) {
ir_node *pred = get_irn_n(irn, i);
if (! rbitset_is_set(env->marks, get_irn_idx(pred))) {
/* not constant predecessor ... */
return;
}
}
/* all predecessors are constant, we probably can fold this node */
rbitset_set(env->marks, get_irn_idx(irn));
if (is_binop(irn)) {
env->weight += const_binop_weight;
} else if (is_unop(irn)) {
env->weight += const_binop_weight;
} else if (is_Proj(irn)) {
ir_node *pred = get_Proj_pred(irn);
if (is_Cmp(pred)) {
env->weight += const_cmp_weight;
} else if (is_Cond(pred)) {
/* the argument is used for a SwitchCond, a big win */
env->weight += const_cmp_weight;
}
}
}
/**
*
*/
unsigned analyze_irg_param_weights(ir_graph *irg, unsigned *bitmask, unsigned len) {
unsigned nodes = get_irg_last_idx(irg);
unsigned *marks = rbitset_malloc(nodes);
walk_env env;
env.marks = marks;
env.param_mask = bitmask;
env.mask_len = len;
env.weight = null_weight;
irg_walk_graph(irg, NULL, evaluate_weight, &env);
xfree(marks);
return env.weight;
}
/**
* Analyze argument's weight of a given
* ir graph.
......
......@@ -1741,9 +1741,12 @@ static void fix_start_block(ir_graph *irg)
panic("Initial exec has no follow block in %+F", irg);
}
static void lower_outer_frame_sels(ir_node *irn, void *env) {
/**
* Update the entity of Sels to the outer value parameters.
*/
static void update_outer_frame_sels(ir_node *irn, void *env) {
lower_frame_sels_env_t *ctx = env;
ir_node *ptr, *bl, *nw;
ir_node *ptr;
ir_entity *ent;
int pos = 0;
......@@ -1760,21 +1763,19 @@ static void lower_outer_frame_sels(ir_node *irn, void *env) {
/* replace by its copy from the argument type */
pos = get_struct_member_index(ctx->value_tp, ent);
ent = get_argument_entity(ent, ctx);
}
bl = get_nodes_block(irn);
nw = be_new_FrameAddr(ctx->link_class, current_ir_graph, bl, ptr, ent);
exchange(irn, nw);
/* check, if it's a param sel and if have not seen this entity before */
if (get_entity_owner(ent) == ctx->value_tp && get_entity_link(ent) == NULL) {
ent_pos_pair pair;
pair.ent = ent;
pair.pos = pos;
pair.next = NULL;
ARR_APP1(ent_pos_pair, ctx->value_param_list, pair);
/* just a mark */
set_entity_link(ent, ctx->value_param_list);
set_Sel_entity(irn, ent);
/* check, if we have not seen this entity before */
if (get_entity_link(ent) == NULL) {
ent_pos_pair pair;
pair.ent = ent;
pair.pos = pos;
pair.next = NULL;
ARR_APP1(ent_pos_pair, ctx->value_param_list, pair);
/* just a mark */
set_entity_link(ent, ctx->value_param_list);
}
}
}
......@@ -1799,7 +1800,7 @@ static void fix_outer_variable_access(be_abi_irg_t *env, lower_frame_sels_env_t
ctx->static_link_pos = 0;
irg = get_entity_irg(ent);
irg_walk_graph(irg, NULL, lower_outer_frame_sels, ctx);
irg_walk_graph(irg, NULL, update_outer_frame_sels, ctx);
}
}
......@@ -2598,9 +2599,45 @@ static void stack_bias_walker(ir_node *bl, void *data)
}
}
/**
* Walker: finally lower all Sels of outer frame or parameter
* entities.
*/
static void lower_outer_frame_sels(ir_node *sel, void *ctx) {
be_abi_irg_t *env = ctx;
ir_node *ptr;
ir_entity *ent;
ir_type *owner;
if (! is_Sel(sel))
return;
ent = get_Sel_entity(sel);
owner = get_entity_owner(ent);
ptr = get_Sel_ptr(sel);
if (owner == env->frame.frame_type || owner == env->frame.arg_type) {
/* found access to outer frame or arguments */
int offset = get_stack_entity_offset(&env->frame, ent, 0);
if (offset != 0) {
ir_node *bl = get_nodes_block(sel);
dbg_info *dbgi = get_irn_dbg_info(sel);
ir_mode *mode = get_irn_mode(sel);
ir_mode *mode_UInt = get_reference_mode_unsigned_eq(mode);
ir_node *cnst = new_r_Const_long(current_ir_graph, mode_UInt, offset);
ptr = new_rd_Add(dbgi, current_ir_graph, bl, ptr, cnst, mode);
}
exchange(sel, ptr);
}
}
void be_abi_fix_stack_bias(be_abi_irg_t *env)
{
ir_graph *irg = env->birg->irg;
ir_graph *irg = env->birg->irg;
ir_type *frame_tp;
int i;
struct bias_walk bw;
stack_frame_compute_initial_offset(&env->frame);
......@@ -2614,6 +2651,19 @@ void be_abi_fix_stack_bias(be_abi_irg_t *env)
bw.env = env;
bw.start_block = get_irg_start_block(irg);
irg_block_walk_graph(irg, stack_bias_walker, NULL, &bw);
/* fix now inner functions: these still have Sel node to outer
frame and parameter entities */
frame_tp = get_irg_frame_type(irg);
for (i = get_class_n_members(frame_tp) - 1; i >= 0; --i) {
ir_entity *ent = get_class_member(frame_tp, i);
if (is_method_entity(ent)) {
ir_graph *irg = get_entity_irg(ent);
irg_walk_graph(irg, NULL, lower_outer_frame_sels, env);
}
}
}
ir_node *be_abi_get_callee_save_irn(be_abi_irg_t *abi, const arch_register_t *reg)
......
......@@ -407,9 +407,10 @@ static ir_node *phi_translate(ir_node *node, ir_node *block, int pos, ir_valuese
if (trans == NULL)
trans = leader;
if (is_Phi(trans) && get_nodes_block(trans) == block)
set_irn_n(nn, i, get_Phi_pred(trans, pos));
else
if (is_Phi(trans) && get_nodes_block(trans) == block) {
ir_node *trans_pred = get_Phi_pred(trans, pos);
set_irn_n(nn, i, trans_pred);
} else
set_irn_n(nn, i, trans);
}
nn = optimize_node(nn);
......
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