Commit 41dc42af authored by Matthias Braun's avatar Matthias Braun
Browse files

big refactoring of arch_XXX functions

This tries to get the names in a consistent format. We basically have 2
views on register allocation/constraints now:

1) Register Requirements and Assigments are per-instruction. Each
   instruction has requirements on its inputs and outputs, register get
   assigned for outputs of an instruction (assignment is an attribute of
   an instruction, not of the Proj-nodes).
   The internal datastructures model this form!

   The functions here have the form:
     arch_get_irn_register_req_in(node, input_nr)
     arch_get_irn_register_in(node, input_nr)
     arch_get_irn_register_req_out(node, output_nr)
     arch_set_irn_register_out(node, output_nr, register)

2) Register Requirements and Assignments are on firm-values. This view
   allows to query/assign requirements and registers at the Proj nodes
   instead of the repsective predecessors.
   This is a convenience interface modeled on top of the other!

   The functions have the form:
     arch_get_irn_register_req(node)
     arch_get_irn_register(node)
     arch_set_irn_register(node, register)
parent ed7cc1da
......@@ -49,15 +49,6 @@
#define SNPRINTF_BUF_LEN 128
/**
* Returns the register at in position pos.
*/
static const arch_register_t *get_in_reg(const ir_node *node, int pos)
{
ir_node *op = get_irn_n(node, pos);
return arch_get_irn_register(op);
}
void TEMPLATE_emit_immediate(const ir_node *node)
{
const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
......@@ -71,13 +62,13 @@ static void emit_register(const arch_register_t *reg)
void TEMPLATE_emit_source_register(const ir_node *node, int pos)
{
const arch_register_t *reg = get_in_reg(node, pos);
const arch_register_t *reg = arch_get_irn_register_in(node, pos);
emit_register(reg);
}
void TEMPLATE_emit_dest_register(const ir_node *node, int pos)
{
const arch_register_t *reg = arch_irn_get_register(node, pos);
const arch_register_t *reg = arch_get_irn_register_out(node, pos);
emit_register(reg);
}
......
......@@ -107,8 +107,8 @@ static void init_TEMPLATE_attributes(ir_node *node, arch_irn_flags_t flags,
backend_info_t *info;
(void) execution_units;
arch_irn_set_flags(node, flags);
arch_set_in_register_reqs(node, in_reqs);
arch_set_irn_flags(node, flags);
arch_set_irn_register_reqs_in(node, in_reqs);
info = be_get_info(node);
info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
......
......@@ -247,7 +247,7 @@ static ir_node *gen_Phi(ir_node *node)
copy_node_attr(irg, node, phi);
be_duplicate_deps(node, phi);
arch_set_out_register_req(phi, 0, req);
arch_set_irn_register_req_out(phi, 0, req);
be_enqueue_preds(node);
return phi;
}
......
......@@ -51,15 +51,6 @@
#include "../benode.h"
/**
* Returns the register at in position pos.
*/
static const arch_register_t *get_in_reg(const ir_node *node, int pos)
{
ir_node *op = get_irn_n(node, pos);
return arch_get_irn_register(op);
}
/*************************************************************
* _ _ __ _ _
* (_) | | / _| | | | |
......@@ -93,12 +84,12 @@ void amd64_emit_fp_offset(const ir_node *node)
void amd64_emit_source_register(const ir_node *node, int pos)
{
amd64_emit_register(get_in_reg(node, pos));
amd64_emit_register(arch_get_irn_register_in(node, pos));
}
void amd64_emit_dest_register(const ir_node *node, int pos)
{
amd64_emit_register(arch_irn_get_register(node, pos));
amd64_emit_register(arch_get_irn_register_out(node, pos));
}
/**
......@@ -332,7 +323,7 @@ static void emit_be_Copy(const ir_node *irn)
{
ir_mode *mode = get_irn_mode(irn);
if (get_in_reg(irn, 0) == arch_irn_get_register(irn, 0)) {
if (arch_get_irn_register_in(irn, 0) == arch_get_irn_register_out(irn, 0)) {
/* omitted Copy */
return;
}
......@@ -454,9 +445,9 @@ static void emit_amd64_binop_op(const ir_node *irn, int second_op)
*/
static void emit_amd64_binop(const ir_node *irn)
{
const arch_register_t *reg_s1 = get_in_reg(irn, 0);
const arch_register_t *reg_s2 = get_in_reg(irn, 1);
const arch_register_t *reg_d1 = arch_irn_get_register(irn, 0);
const arch_register_t *reg_s1 = arch_get_irn_register_in(irn, 0);
const arch_register_t *reg_s2 = arch_get_irn_register_in(irn, 1);
const arch_register_t *reg_d1 = arch_get_irn_register_out(irn, 0);
int second_op = 0;
......
......@@ -129,8 +129,8 @@ static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
backend_info_t *info;
(void) execution_units;
arch_irn_set_flags(node, flags);
arch_set_in_register_reqs(node, in_reqs);
arch_set_irn_flags(node, flags);
arch_set_irn_register_reqs_in(node, in_reqs);
info = be_get_info(node);
info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
......
......@@ -116,7 +116,7 @@ sub amd64_custom_init_attr {
my $res = "";
if(defined($node->{modified_flags})) {
$res .= "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n";
$res .= "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);\n";
}
return $res;
}
......
......@@ -180,7 +180,7 @@ static ir_node *gen_Jmp(ir_node *node)
static ir_node *gen_be_Call(ir_node *node)
{
ir_node *res = be_duplicate_node(node);
arch_irn_add_flags(res, arch_irn_flags_modify_flags);
arch_add_irn_flags(res, arch_irn_flags_modify_flags);
return res;
}
......@@ -330,7 +330,7 @@ static ir_node *gen_Phi(ir_node *node)
copy_node_attr(irg, node, phi);
be_duplicate_deps(node, phi);
arch_set_out_register_req(phi, 0, req);
arch_set_irn_register_req_out(phi, 0, req);
be_enqueue_preds(node);
......
......@@ -65,15 +65,6 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
static set *sym_or_tv;
static arm_isa_t *isa;
/**
* Returns the register at in position pos.
*/
static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
{
ir_node *op = get_irn_n(irn, pos);
return arch_get_irn_register(op);
}
static void arm_emit_register(const arch_register_t *reg)
{
be_emit_string(arch_register_get_name(reg));
......@@ -81,13 +72,13 @@ static void arm_emit_register(const arch_register_t *reg)
void arm_emit_source_register(const ir_node *node, int pos)
{
const arch_register_t *reg = get_in_reg(node, pos);
const arch_register_t *reg = arch_get_irn_register_in(node, pos);
arm_emit_register(reg);
}
void arm_emit_dest_register(const ir_node *node, int pos)
{
const arch_register_t *reg = arch_irn_get_register(node, pos);
const arch_register_t *reg = arch_get_irn_register_out(node, pos);
arm_emit_register(reg);
}
......@@ -450,16 +441,16 @@ static void emit_arm_CopyB(const ir_node *irn)
const arm_CopyB_attr_t *attr = get_arm_CopyB_attr_const(irn);
unsigned size = attr->size;
const char *tgt = arch_register_get_name(get_in_reg(irn, 0));
const char *src = arch_register_get_name(get_in_reg(irn, 1));
const char *tgt = arch_register_get_name(arch_get_irn_register_in(irn, 0));
const char *src = arch_register_get_name(arch_get_irn_register_in(irn, 1));
const char *t0, *t1, *t2, *t3;
const arch_register_t *tmpregs[4];
/* collect the temporary registers and sort them, we need ascending order */
tmpregs[0] = get_in_reg(irn, 2);
tmpregs[1] = get_in_reg(irn, 3);
tmpregs[2] = get_in_reg(irn, 4);
tmpregs[0] = arch_get_irn_register_in(irn, 2);
tmpregs[1] = arch_get_irn_register_in(irn, 3);
tmpregs[2] = arch_get_irn_register_in(irn, 4);
tmpregs[3] = &arm_registers[REG_R12];
/* Note: R12 is always the last register because the RA did not assign higher ones */
......@@ -691,7 +682,7 @@ static void emit_be_Copy(const ir_node *irn)
{
ir_mode *mode = get_irn_mode(irn);
if (get_in_reg(irn, 0) == arch_irn_get_register(irn, 0)) {
if (arch_get_irn_register_in(irn, 0) == arch_get_irn_register_out(irn, 0)) {
/* omitted Copy */
return;
}
......
......@@ -360,8 +360,8 @@ static void init_arm_attributes(ir_node *node, arch_irn_flags_t flags,
backend_info_t *info;
(void) execution_units;
arch_irn_set_flags(node, flags);
arch_set_in_register_reqs(node, in_reqs);
arch_set_irn_flags(node, flags);
arch_set_irn_register_reqs_in(node, in_reqs);
attr->is_load_store = false;
info = be_get_info(node);
......
......@@ -312,7 +312,7 @@ LinkMovPC => {
attr_type => "arm_shifter_operand_t",
attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
"\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);",
"\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);",
emit => ". mov lr, pc\n".
". mov pc, %SO",
},
......@@ -325,7 +325,7 @@ LinkLdrPC => {
out_arity => "variable",
attr_type => "arm_load_store_attr_t",
attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
emit => ". mov lr, pc\n".
". ldr pc, %SO",
},
......@@ -336,7 +336,7 @@ Bl => {
out_arity => "variable",
attr_type => "arm_SymConst_attr_t",
attr => "ir_entity *entity, int symconst_offset",
custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
emit => '. bl %SC',
},
......
......@@ -1543,11 +1543,11 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
*/
static int find_out_for_reg(ir_node *node, const arch_register_t *reg)
{
int n_outs = arch_irn_get_n_outs(node);
int n_outs = arch_get_irn_n_outs(node);
int o;
for (o = 0; o < n_outs; ++o) {
const arch_register_req_t *req = arch_get_out_register_req(node, o);
const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
if (req == reg->single_req)
return o;
}
......@@ -2011,13 +2011,13 @@ static ir_node *gen_Call(ir_node *node)
pmap_insert(node_to_stack, node, incsp);
}
arch_set_in_register_reqs(res, in_req);
arch_set_irn_register_reqs_in(res, in_req);
/* create output register reqs */
arch_set_out_register_req(res, 0, arch_no_register_req);
arch_set_irn_register_req_out(res, 0, arch_no_register_req);
for (o = 0; o < n_caller_saves; ++o) {
const arch_register_t *reg = caller_saves[o];
arch_set_out_register_req(res, o+1, reg->single_req);
arch_set_irn_register_req_out(res, o+1, reg->single_req);
}
/* copy pinned attribute */
......@@ -2072,7 +2072,7 @@ static ir_node *gen_Phi(ir_node *node)
copy_node_attr(irg, node, phi);
be_duplicate_deps(node, phi);
arch_set_out_register_req(phi, 0, req);
arch_set_irn_register_req_out(phi, 0, req);
be_enqueue_preds(node);
......
......@@ -118,6 +118,32 @@ static void be_abi_reg_map_set(pmap *map, const arch_register_t* reg,
pmap_insert(map, reg, node);
}
/**
* Check if the given register is callee save, ie. will be save by the callee.
*/
static bool arch_register_is_callee_save(
const arch_env_t *arch_env,
const arch_register_t *reg)
{
if (arch_env->impl->register_saved_by)
return arch_env->impl->register_saved_by(reg, /*callee=*/1);
return false;
}
/**
* Check if the given register is caller save, ie. must be save by the caller.
*/
static bool arch_register_is_caller_save(
const arch_env_t *arch_env,
const arch_register_t *reg)
{
if (arch_env->impl->register_saved_by)
return arch_env->impl->register_saved_by(reg, /*callee=*/0);
return false;
}
/*
_ ____ ___ ____ _ _ _ _
/ \ | __ )_ _| / ___|__ _| | | |__ __ _ ___| | _____
......@@ -581,8 +607,8 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
/* add state registers ins */
for (s = 0; s < ARR_LEN(states); ++s) {
const arch_register_t *reg = states[s];
const arch_register_class_t *cls = arch_register_get_class(reg);
ir_node *regnode = new_r_Unknown(irg, arch_register_class_mode(cls));
const arch_register_class_t *cls = reg->reg_class;
ir_node *regnode = new_r_Unknown(irg, cls->mode);
in[n_ins++] = regnode;
}
assert(n_ins == (int) (n_reg_params + ARR_LEN(states)));
......@@ -732,7 +758,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
keep = be_new_Keep(bl, n, in);
for (i = 0; i < n; ++i) {
const arch_register_t *reg = (const arch_register_t*)get_irn_link(in[i]);
be_node_set_reg_class_in(keep, i, reg->reg_class);
be_node_set_reg_class_in(keep, i, arch_register_get_class(reg));
}
}
......@@ -1569,7 +1595,7 @@ static void modify_irg(ir_graph *irg)
/* create a new initial memory proj */
assert(is_Proj(old_mem));
arch_set_out_register_req(env->start, 0, arch_no_register_req);
arch_set_irn_register_req_out(env->start, 0, arch_no_register_req);
new_mem_proj = new_r_Proj(env->start, mode_M, 0);
mem = new_mem_proj;
set_irg_initial_mem(irg, mem);
......
......@@ -274,12 +274,12 @@ ir_node *be_prolog_create_start(beabi_helper_env_t *env, dbg_info *dbgi,
const arch_register_t *reg = regflag->reg;
ir_node *proj;
if (reg == NULL) {
arch_set_out_register_req(start, o, arch_no_register_req);
arch_set_irn_register_req_out(start, o, arch_no_register_req);
proj = new_r_Proj(start, mode_M, o);
} else {
be_set_constr_single_reg_out(start, o, regflag->reg,
regflag->flags);
arch_irn_set_register(start, o, regflag->reg);
arch_set_irn_register_out(start, o, regflag->reg);
proj = new_r_Proj(start, reg->reg_class->mode, o);
}
env->prolog.value_map[o] = proj;
......@@ -422,7 +422,7 @@ static void add_missing_keep_walker(ir_node *node, void *data)
(void) data;
if (mode != mode_T) {
if (!has_real_user(node)) {
const arch_register_req_t *req = arch_get_register_req_out(node);
const arch_register_req_t *req = arch_get_irn_register_req(node);
const arch_register_class_t *cls = req->cls;
if (cls == NULL
|| (cls->flags & arch_register_class_flag_manual_ra)) {
......@@ -434,7 +434,7 @@ static void add_missing_keep_walker(ir_node *node, void *data)
return;
}
n_outs = arch_irn_get_n_outs(node);
n_outs = arch_get_irn_n_outs(node);
if (n_outs <= 0)
return;
......@@ -470,7 +470,7 @@ static void add_missing_keep_walker(ir_node *node, void *data)
continue;
}
req = arch_get_out_register_req(node, i);
req = arch_get_irn_register_req_out(node, i);
cls = req->cls;
if (cls == NULL || (cls->flags & arch_register_class_flag_manual_ra)) {
continue;
......
......@@ -40,6 +40,21 @@
#include "irprintf.h"
static const arch_register_req_t no_requirement = {
arch_register_req_type_none,
NULL,
NULL,
0,
0,
0
};
const arch_register_req_t *arch_no_register_req = &no_requirement;
static reg_out_info_t dummy_info = {
NULL,
&no_requirement
};
/* Initialize the architecture environment struct. */
arch_env_t *arch_env_init(const arch_isa_if_t *isa_if, FILE *file_handle, be_main_env_t *main_env)
{
......@@ -53,7 +68,7 @@ arch_env_t *arch_env_init(const arch_isa_if_t *isa_if, FILE *file_handle, be_mai
* @param irn The node to get the responsible isa for.
* @return The irn operations given by the responsible isa.
*/
static inline const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
static const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
{
const ir_op *ops;
const arch_irn_ops_t *be_ops;
......@@ -69,22 +84,6 @@ static inline const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
return be_ops;
}
const arch_register_req_t *arch_get_register_req(const ir_node *irn, int pos)
{
if (is_Proj(irn)) {
ir_node *pred = get_Proj_pred(irn);
long pn = get_Proj_proj(irn);
assert(pos == -1);
return arch_get_out_register_req(pred, pn);
}
if (pos < 0) {
return arch_get_out_register_req(irn, -pos-1);
} else {
return arch_get_in_register_req(irn, pos);
}
}
void arch_set_frame_offset(ir_node *irn, int offset)
{
const arch_irn_ops_t *ops = get_irn_ops(irn);
......@@ -147,37 +146,10 @@ int arch_get_op_estimated_cost(const ir_node *irn)
}
}
int arch_reg_is_allocatable(const ir_node *irn, int pos,
const arch_register_t *reg)
{
const arch_register_req_t *req = arch_get_register_req(irn, pos);
if (req->type == arch_register_req_type_none)
return 0;
if (arch_register_req_is(req, limited)) {
if (arch_register_get_class(reg) != req->cls)
return 0;
return rbitset_is_set(req->limited, arch_register_get_index(reg));
}
return req->cls == reg->reg_class;
}
const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
static reg_out_info_t *get_out_info(const ir_node *node)
{
const arch_register_req_t *req = arch_get_register_req(irn, pos);
assert(req->type != arch_register_req_type_none || req->cls == NULL);
return req->cls;
}
static inline reg_out_info_t *get_out_info(const ir_node *node)
{
size_t pos = 0;
size_t pos = 0;
const backend_info_t *info;
assert(get_irn_mode(node) != mode_T);
if (is_Proj(node)) {
pos = get_Proj_proj(node);
......@@ -185,12 +157,17 @@ static inline reg_out_info_t *get_out_info(const ir_node *node)
}
info = be_get_info(node);
/* We have a problem with the switch-node where there can be arbitrary
* Proj-numbers, so we can't easily allocate an array big-enough to hold
* all of them. So until we rewrite Switch-nodes we need this special case
*/
if (info->out_infos == NULL)
return &dummy_info;
assert(pos < ARR_LEN(info->out_infos));
return &info->out_infos[pos];
}
static inline reg_out_info_t *get_out_info_n(const ir_node *node, int pos)
static reg_out_info_t *get_out_info_n(const ir_node *node, int pos)
{
const backend_info_t *info = be_get_info(node);
assert(!is_Proj(node));
......@@ -205,13 +182,20 @@ const arch_register_t *arch_get_irn_register(const ir_node *node)
return out->reg;
}
const arch_register_t *arch_irn_get_register(const ir_node *node, int pos)
const arch_register_t *arch_get_irn_register_out(const ir_node *node, int pos)
{
const reg_out_info_t *out = get_out_info_n(node, pos);
return out->reg;
}
void arch_irn_set_register(ir_node *node, int pos, const arch_register_t *reg)
const arch_register_t *arch_get_irn_register_in(const ir_node *node, int pos)
{
ir_node *op = get_irn_n(node, pos);
return arch_get_irn_register(op);
}
void arch_set_irn_register_out(ir_node *node, int pos,
const arch_register_t *reg)
{
reg_out_info_t *out = get_out_info_n(node, pos);
out->reg = reg;
......@@ -223,30 +207,63 @@ void arch_set_irn_register(ir_node *node, const arch_register_t *reg)
out->reg = reg;
}
const arch_register_req_t *arch_get_irn_register_req(const ir_node *node)
{
reg_out_info_t *out = get_out_info(node);
return out->req;
}
arch_irn_class_t arch_irn_classify(const ir_node *node)
{
const arch_irn_ops_t *ops = get_irn_ops(node);
return ops->classify(node);
}
arch_irn_flags_t arch_irn_get_flags(const ir_node *node)
arch_irn_flags_t arch_get_irn_flags(const ir_node *node)
{
backend_info_t *info = be_get_info(node);
backend_info_t *info;
if (is_Proj(node))
return arch_irn_flags_not_scheduled;
info = be_get_info(node);
return info->flags;
}
void arch_irn_set_flags(ir_node *node, arch_irn_flags_t flags)
void arch_set_irn_flags(ir_node *node, arch_irn_flags_t flags)
{
backend_info_t *info = be_get_info(node);
backend_info_t *info;
/* setting flags is only supported for instructions currently.
* (mainly because we found no use for it yet and saved the space for
* be_infos for them */
assert(!is_Proj(node));
info = be_get_info(node);
info->flags = flags;
}
void arch_irn_add_flags(ir_node *node, arch_irn_flags_t flags)
void arch_add_irn_flags(ir_node *node, arch_irn_flags_t flags)
{
backend_info_t *info = be_get_info(node);
backend_info_t *info;
assert(!is_Proj(node));
info = be_get_info(node);
info->flags |= flags;
}
bool arch_reg_is_allocatable(const arch_register_req_t *req,
const arch_register_t *reg)
{
if (reg->type & arch_register_type_joker)
return true;
if (req->type == arch_register_req_type_none)
return false;
if (req->type & arch_register_req_type_limited) {
if (arch_register_get_class(reg) != req->cls)
return false;
return rbitset_is_set(req->limited, arch_register_get_index(reg));
}
return req->cls == arch_register_get_class(reg);
}
void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
const ir_node *node)
{
......@@ -311,25 +328,25 @@ void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
void arch_dump_reqs_and_registers(FILE *F, const ir_node *node)
{
int n_ins = get_irn_arity(node);
int n_outs = arch_irn_get_n_outs(node);
arch_irn_flags_t flags = arch_irn_get_flags(node);
int n_outs = arch_get_irn_n_outs(node);
arch_irn_flags_t flags = arch_get_irn_flags(node);
int i;
for (i = 0; i < n_ins; ++i) {
const arch_register_req_t *req = arch_get_in_register_req(node, i);
const arch_register_req_t *req = arch_get_irn_register_req_in(node, i);
fprintf(F, "inreq #%d = ", i);
arch_dump_register_req(F, req, node);
fputs("\n", F);
}
for (i = 0; i < n_outs; ++i) {
const arch_register_req_t *req = arch_get_out_register_req(node, i);
const arch_register_req_t *req = arch_get_irn_register_req_out(node, i);
fprintf(F, "outreq #%d = ", i);