Commit b4647d67 authored by Matthias Braun's avatar Matthias Braun
Browse files

backend: put ignore regs into beirg

[r28072]
parent 6c3146b9
......@@ -30,8 +30,17 @@
#include "typerep.h"
#include "xmalloc.h"
#include "error.h"
#include "util.h"
calling_convention_t *arm_decide_calling_convention(ir_type *function_type)
static const unsigned ignore_regs[] = {
REG_R12,
REG_SP,
REG_PC,
REG_FL,
};
calling_convention_t *arm_decide_calling_convention(ir_graph *irg,
ir_type *function_type)
{
int stack_offset = 0;
reg_or_stackslot_t *params;
......@@ -125,6 +134,21 @@ calling_convention_t *arm_decide_calling_convention(ir_type *function_type)
cconv->param_stack_size = stack_offset;
cconv->results = results;
/* setup allocatable registers */
if (irg != NULL) {
be_irg_t *birg = be_birg_from_irg(irg);
size_t n_ignores = ARRAY_SIZE(ignore_regs);
struct obstack *obst = &birg->obst;
size_t r;
assert(birg->allocatable_regs == NULL);
birg->allocatable_regs = rbitset_obstack_alloc(obst, N_ARM_REGISTERS);
rbitset_set_all(birg->allocatable_regs, N_ARM_REGISTERS);
for (r = 0; r < n_ignores; ++r) {
rbitset_clear(birg->allocatable_regs, ignore_regs[r]);
}
}
return cconv;
}
......
......@@ -102,7 +102,8 @@ typedef struct calling_convention_t
* Decides what goes to register or to stack and what stack offsets/
* datatypes are used.
*/
calling_convention_t *arm_decide_calling_convention(ir_type *function_type);
calling_convention_t *arm_decide_calling_convention(ir_graph *irg,
ir_type *function_type);
/**
* free memory used by a calling_convention_t
......
......@@ -1525,7 +1525,8 @@ static ir_node *gen_Proj_Proj_Call(ir_node *node)
ir_node *call = get_Proj_pred(get_Proj_pred(node));
ir_node *new_call = be_transform_node(call);
ir_type *function_type = get_Call_type(call);
calling_convention_t *cconv = arm_decide_calling_convention(function_type);
calling_convention_t *cconv
= arm_decide_calling_convention(NULL, function_type);
const reg_or_stackslot_t *res = &cconv->results[pn];
ir_mode *mode;
int regn;
......@@ -1844,7 +1845,7 @@ static ir_node *gen_Call(ir_node *node)
ir_node *new_mem = be_transform_node(mem);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_type *type = get_Call_type(node);
calling_convention_t *cconv = arm_decide_calling_convention(type);
calling_convention_t *cconv = arm_decide_calling_convention(NULL, type);
int n_params = get_Call_n_params(node);
int n_param_regs = sizeof(param_regs)/sizeof(param_regs[0]);
/* max inputs: memory, callee, register arguments */
......@@ -2171,7 +2172,7 @@ void arm_transform_graph(ir_graph *irg)
abihelper = be_abihelper_prepare(irg);
be_collect_stacknodes(abihelper);
assert(cconv == NULL);
cconv = arm_decide_calling_convention(get_entity_type(entity));
cconv = arm_decide_calling_convention(irg, get_entity_type(entity));
create_stacklayout(irg);
be_transform_graph(irg, NULL);
......
......@@ -102,7 +102,6 @@ struct be_abi_irg_t {
void *cb; /**< ABI Callback self pointer. */
pmap *keep_map; /**< mapping blocks to keep nodes. */
pset *ignore_regs; /**< Additional registers which shall be ignored. */
ir_node **calls; /**< flexible array containing all be_Call nodes */
};
......@@ -1703,6 +1702,7 @@ static void modify_irg(ir_graph *irg)
const arch_env_t *arch_env = be_get_irg_arch_env(irg);
const arch_register_t *sp = arch_env->sp;
ir_type *method_type = get_entity_type(get_irg_entity(irg));
be_irg_t *birg = be_birg_from_irg(irg);
struct obstack *obst = be_get_be_obst(irg);
be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg);
ir_node *end;
......@@ -1901,7 +1901,7 @@ static void modify_irg(ir_graph *irg)
frame_pointer = be_abi_reg_map_get(env->regs, fp_reg);
set_irg_frame(irg, frame_pointer);
pset_insert_ptr(env->ignore_regs, fp_reg);
rbitset_clear(birg->allocatable_regs, fp_reg->global_index);
/* rewire old mem users to new mem */
exchange(old_mem, mem);
......@@ -2185,19 +2185,28 @@ be_abi_irg_t *be_abi_introduce(ir_graph *irg)
const arch_env_t *arch_env = be_get_irg_arch_env(irg);
ir_entity *entity = get_irg_entity(irg);
ir_type *method_type = get_entity_type(entity);
be_irg_t *birg = be_birg_from_irg(irg);
struct obstack *obst = &birg->obst;
unsigned r;
pmap_entry *ent;
ir_node *dummy;
env->ignore_regs = pset_new_ptr_default();
/* determine allocatable registers */
assert(birg->allocatable_regs == NULL);
birg->allocatable_regs = rbitset_obstack_alloc(obst, arch_env->n_registers);
for (r = 0; r < arch_env->n_registers; ++r) {
const arch_register_t *reg = &arch_env->registers[r];
if ( !(reg->type & arch_register_type_ignore)) {
rbitset_set(birg->allocatable_regs, r);
}
}
/* break here if backend provides a custom API.
* Note: we shouldn't have to setup any be_abi_irg_t* stuff at all,
* but need more cleanup to make this work
*/
be_set_irg_abi(irg, env);
if (arch_env->custom_abi)
return env;
be_omit_fp = options->omit_fp;
......@@ -2259,8 +2268,6 @@ void be_abi_free(ir_graph *irg)
be_abi_call_free(env->call);
if (env->dce_survivor != NULL)
free_survive_dce(env->dce_survivor);
if (env->ignore_regs != NULL)
del_pset(env->ignore_regs);
if (env->regs != NULL)
pmap_destroy(env->regs);
free(env);
......@@ -2271,23 +2278,16 @@ void be_abi_free(ir_graph *irg)
void be_put_allocatable_regs(const ir_graph *irg,
const arch_register_class_t *cls, bitset_t *bs)
{
be_abi_irg_t *abi = be_get_irg_abi(irg);
const arch_register_t *reg;
unsigned i;
be_irg_t *birg = be_birg_from_irg(irg);
unsigned *allocatable_regs = birg->allocatable_regs;
unsigned i;
assert(bitset_size(bs) == cls->n_regs);
bitset_clear_all(bs);
for (i = 0; i < cls->n_regs; ++i) {
reg = &cls->regs[i];
if (! (reg->type & arch_register_type_ignore))
bitset_set(bs, reg->index);
}
for (reg = pset_first(abi->ignore_regs); reg != NULL;
reg = pset_next(abi->ignore_regs)) {
if (reg->reg_class == cls)
bitset_clear(bs, reg->index);
const arch_register_t *reg = &cls->regs[i];
if (rbitset_is_set(allocatable_regs, reg->global_index))
bitset_set(bs, i);
}
}
......@@ -2303,23 +2303,15 @@ void be_set_allocatable_regs(const ir_graph *irg,
const arch_register_class_t *cls,
unsigned *raw_bitset)
{
be_abi_irg_t *abi = be_get_irg_abi(irg);
unsigned i;
arch_register_t *reg;
be_irg_t *birg = be_birg_from_irg(irg);
unsigned *allocatable_regs = birg->allocatable_regs;
unsigned i;
rbitset_clear_all(raw_bitset, cls->n_regs);
for (i = 0; i < cls->n_regs; ++i) {
if (arch_register_type_is(&cls->regs[i], ignore))
continue;
rbitset_set(raw_bitset, i);
}
for (reg = pset_first(abi->ignore_regs); reg != NULL;
reg = pset_next(abi->ignore_regs)) {
if (reg->reg_class != cls)
continue;
rbitset_clear(raw_bitset, reg->index);
const arch_register_t *reg = &cls->regs[i];
if (rbitset_is_set(allocatable_regs, reg->global_index))
rbitset_set(raw_bitset, i);
}
}
......
......@@ -56,18 +56,18 @@ void be_free_birg(ir_graph *irg);
* - frame_type: A class type describing the frame layout.
*/
struct be_stack_layout_t {
ir_type *arg_type; /**< A type describing the stack argument layout. */
ir_type *between_type; /**< A type describing the "between" layout. */
ir_type *frame_type; /**< The frame type. */
ir_type *order[N_FRAME_TYPES]; /**< arg, between and frame types ordered. */
ir_entity **param_map; /**< An array mapping type parameters to arg_type entries */
int initial_offset; /**< the initial difference between stack pointer and frame pointer */
int initial_bias; /**< the initial stack bias */
int stack_dir; /**< -1 for decreasing, 1 for increasing. */
bool sp_relative : 1; /**< entities are addressed relative to
stack pointer (omit-fp mode) */
ir_type *arg_type; /**< A type describing the stack argument layout. */
ir_type *between_type; /**< A type describing the "between" layout. */
ir_type *frame_type; /**< The frame type. */
ir_type *order[N_FRAME_TYPES]; /**< arg, between and frame types ordered. */
ir_entity **param_map; /**< An array mapping type parameters to arg_type entries */
int initial_offset; /**< the initial difference between stack pointer and frame pointer */
int initial_bias; /**< the initial stack bias */
int stack_dir; /**< -1 for decreasing, 1 for increasing. */
bool sp_relative : 1; /**< entities are addressed relative to
stack pointer (omit-fp mode) */
};
/**
......@@ -82,6 +82,8 @@ typedef struct be_irg_t {
be_dom_front_info_t *dom_front;
be_lv_t *lv;
be_stack_layout_t stack_layout;
unsigned *allocatable_regs; /**< registers available for the
allocator */
arch_register_req_t *sp_req; /**< requirements for stackpointer producing
nodes. */
struct obstack obst; /**< birg obstack (mainly used to keep
......
......@@ -591,11 +591,10 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
arch_env->impl->before_abi(irg);
/* implement the ABI conventions. */
be_timer_push(T_ABI);
be_abi_introduce(irg);
be_timer_pop(T_ABI);
if (!arch_env->custom_abi) {
be_timer_push(T_ABI);
be_abi_introduce(irg);
be_timer_pop(T_ABI);
dump(DUMP_ABI, irg, "abi");
}
......@@ -760,9 +759,11 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
dump(DUMP_FINAL, irg, "end");
be_timer_push(T_ABI);
be_abi_free(irg);
be_timer_pop(T_ABI);
if (!arch_env->custom_abi) {
be_timer_push(T_ABI);
be_abi_free(irg);
be_timer_pop(T_ABI);
}
restore_optimization_state(&state);
......
......@@ -30,7 +30,26 @@
#include "irgwalk.h"
#include "typerep.h"
#include "xmalloc.h"
#include "util.h"
#include "error.h"
#include "gen_sparc_regalloc_if.h"
static const unsigned ignore_regs[] = {
REG_G0,
/* reserved for sparc ABI: */
REG_G5,
REG_G6,
REG_G7,
REG_SP,
REG_O7,
REG_FRAME_POINTER,
REG_I7,
REG_FPFLAGS,
REG_FLAGS,
REG_Y,
};
/**
* Maps an input register representing the i'th register input
......@@ -63,20 +82,18 @@ static void check_omit_fp(ir_node *node, void *env)
calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
ir_graph *irg)
{
int stack_offset = 0;
int stack_offset = 0;
int n_param_regs = ARRAY_SIZE(param_regs);
int n_float_result_regs = ARRAY_SIZE(float_result_regs);
bool omit_fp = false;
reg_or_stackslot_t *params;
reg_or_stackslot_t *results;
int n_param_regs
= sizeof(param_regs)/sizeof(param_regs[0]);
int n_float_result_regs
= sizeof(float_result_regs)/sizeof(float_result_regs[0]);
int n_params;
int n_results;
int i;
int regnum;
int float_regnum;
calling_convention_t *cconv;
bool omit_fp = false;
if (irg != NULL) {
const be_options_t *options = be_get_irg_options(irg);
......@@ -168,6 +185,21 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
cconv->results = results;
cconv->omit_fp = omit_fp;
/* setup ignore register array */
if (irg != NULL) {
be_irg_t *birg = be_birg_from_irg(irg);
size_t n_ignores = ARRAY_SIZE(ignore_regs);
struct obstack *obst = &birg->obst;
size_t r;
assert(birg->allocatable_regs == NULL);
birg->allocatable_regs = rbitset_obstack_alloc(obst, N_SPARC_REGISTERS);
rbitset_set_all(birg->allocatable_regs, N_SPARC_REGISTERS);
for (r = 0; r < n_ignores; ++r) {
rbitset_clear(birg->allocatable_regs, ignore_regs[r]);
}
}
return cconv;
}
......
......@@ -710,7 +710,7 @@ static ir_node *gen_Not(ir_node *node)
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *new_op = be_transform_node(op);
/* Note: Not(Eor()) is normalize in firm locatopts already so
/* Note: Not(Eor()) is normalize in firm localopts already so
* we don't match it for xnor here */
/* Not can be represented with xnor 0, n */
......
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