Commit 223381b3 authored by Matthias Braun's avatar Matthias Braun
Browse files

- Reworked backends to put out register_requirements into backend_info_t

- Add a generic requirements+register+flag dumper to bearch; This avoids all
  backends/benode having their own slightly different dumpers
- Lots of cleanups in the backends along the way

[r26542]
parent 92632c2c
......@@ -42,7 +42,6 @@
#include "gen_TEMPLATE_emitter.h"
#include "TEMPLATE_nodes_attr.h"
#include "TEMPLATE_new_nodes.h"
#include "TEMPLATE_map_regs.h"
#define SNPRINTF_BUF_LEN 128
......
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Register mapping for firm nodes. Stolen from bearch_firm :)
* @version $Id$
*/
#include "config.h"
#include <stdlib.h>
#include "TEMPLATE_map_regs.h"
#include "TEMPLATE_new_nodes.h"
/* Mapping to store registers in firm nodes */
struct TEMPLATE_irn_reg_assoc {
const ir_node *irn;
const arch_register_t *reg;
};
int TEMPLATE_cmp_irn_reg_assoc(const void *a, const void *b, size_t size) {
const struct TEMPLATE_irn_reg_assoc *x = a;
const struct TEMPLATE_irn_reg_assoc *y = b;
(void) size;
return x->irn != y->irn;
}
static struct TEMPLATE_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set) {
struct TEMPLATE_irn_reg_assoc templ;
unsigned int hash;
templ.irn = irn;
templ.reg = NULL;
hash = HASH_PTR(irn);
return set_insert(reg_set, &templ, sizeof(templ), hash);
}
void TEMPLATE_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) {
struct TEMPLATE_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
assoc->reg = reg;
}
const arch_register_t *TEMPLATE_get_firm_reg(const ir_node *irn, set *reg_set) {
struct TEMPLATE_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
return assoc->reg;
}
/**
* Translates the projnum into a "real" argument position for register
* requirements dependend on the predecessor.
*/
long TEMPLATE_translate_proj_pos(const ir_node *proj) {
ir_node *pred = get_Proj_pred(proj);
long nr = get_Proj_proj(proj);
if (is_TEMPLATE_Load(pred)) {
if (nr == pn_Load_res)
return 0;
assert(0 && "unsupported Proj(Load) number");
}
else if (is_TEMPLATE_Store(pred)) {
return 0;
}
else if (is_TEMPLATE_fDiv(pred)) {
if (nr == pn_Quot_res)
return 0;
else
assert(0 && "there should be no more Projs for a fDiv");
}
// assert(0 && "unsupported Proj(X)");
return nr;
}
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief declarations for the register allocation interface
* @version $Id$
*/
#ifndef FIRM_BE_TEMPLATE_TEMPLATE_MAP_REGS_H
#define FIRM_BE_TEMPLATE_TEMPLATE_MAP_REGS_H
#include "irnode.h"
#include "set.h"
#include "../bearch.h"
#include "TEMPLATE_nodes_attr.h"
int TEMPLATE_cmp_irn_reg_assoc(const void *a, const void *b, size_t len);
void TEMPLATE_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set);
const arch_register_t *TEMPLATE_get_firm_reg(const ir_node *irn, set *reg_set);
long TEMPLATE_translate_proj_pos(const ir_node *proj);
#endif
......@@ -58,32 +58,6 @@
* |_|
***********************************************************************************/
/**
* Dumps the register requirements for either in or out.
*/
static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
int inout) {
char *dir = inout ? "out" : "in";
int max = inout ? (int) arch_irn_get_n_outs(n) : get_irn_arity(n);
char buf[1024];
int i;
memset(buf, 0, sizeof(buf));
if (reqs) {
for (i = 0; i < max; i++) {
fprintf(F, "%sreq #%d =", dir, i);
arch_dump_register_req(F, reqs[i], n);
fprintf(F, "\n");
}
fprintf(F, "\n");
} else {
fprintf(F, "%sreq = N/A\n", dir);
}
}
/**
* Dumper interface for dumping TEMPLATE nodes in vcg.
* @param n the node to dump
......@@ -91,93 +65,39 @@ static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
* @param reason indicates which kind of information should be dumped
* @return 0 on success or != 0 on failure
*/
static int TEMPLATE_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
ir_mode *mode = NULL;
int bad = 0;
int i, n_res, flags;
const arch_register_req_t **reqs;
static int TEMPLATE_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
{
ir_mode *mode = NULL;
switch (reason) {
case dump_node_opcode_txt:
fprintf(F, "%s", get_irn_opname(n));
break;
case dump_node_mode_txt:
mode = get_irn_mode(n);
if (mode) {
fprintf(F, "[%s]", get_mode_name(mode));
}
else {
fprintf(F, "[?NOMODE?]");
}
break;
case dump_node_nodeattr_txt:
/* TODO: dump some attributes which should show up */
/* in node name in dump (e.g. consts or the like) */
break;
case dump_node_info_txt:
fprintf(F, "=== TEMPLATE attr begin ===\n");
/* dump IN requirements */
if (get_irn_arity(n) > 0) {
reqs = get_TEMPLATE_in_req_all(n);
dump_reg_req(F, n, reqs, 0);
}
n_res = arch_irn_get_n_outs(n);
if (n_res > 0) {
/* dump OUT requirements */
reqs = get_TEMPLATE_out_req_all(n);
dump_reg_req(F, n, reqs, 1);
/* dump assigned registers */
for (i = 0; i < n_res; i++) {
const arch_register_t *reg = arch_irn_get_register(n, i);
fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
}
fprintf(F, "\n");
}
/* dump n_res */
fprintf(F, "n_res = %d\n", n_res);
/* dump flags */
fprintf(F, "flags =");
flags = arch_irn_get_flags(n);
if (flags == arch_irn_flags_none) {
fprintf(F, " none");
}
else {
if (flags & arch_irn_flags_dont_spill) {
fprintf(F, " unspillable");
}
if (flags & arch_irn_flags_rematerializable) {
fprintf(F, " remat");
}
if (flags & arch_irn_flags_modify_flags) {
fprintf(F, " modify_flags");
}
}
fprintf(F, " (%d)\n", flags);
/* TODO: dump all additional attributes */
fprintf(F, "=== TEMPLATE attr end ===\n");
/* end of: case dump_node_info_txt */
break;
}
case dump_node_opcode_txt:
fprintf(F, "%s", get_irn_opname(n));
break;
case dump_node_mode_txt:
mode = get_irn_mode(n);
return bad;
}
if (mode) {
fprintf(F, "[%s]", get_mode_name(mode));
} else {
fprintf(F, "[?NOMODE?]");
}
break;
case dump_node_nodeattr_txt:
/* TODO: dump some attributes which should show up */
/* in node name in dump (e.g. consts or the like) */
break;
case dump_node_info_txt:
arch_dump_reqs_and_registers(F, n);
break;
}
return 0;
}
/***************************************************************************************************
* _ _ _ __ _ _ _ _
......@@ -190,12 +110,14 @@ static int TEMPLATE_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
* |___/
***************************************************************************************************/
const TEMPLATE_attr_t *get_TEMPLATE_attr_const(const ir_node *node) {
const TEMPLATE_attr_t *get_TEMPLATE_attr_const(const ir_node *node)
{
assert(is_TEMPLATE_irn(node) && "need TEMPLATE node to get attributes");
return (const TEMPLATE_attr_t *)get_irn_generic_attr_const(node);
}
TEMPLATE_attr_t *get_TEMPLATE_attr(ir_node *node) {
TEMPLATE_attr_t *get_TEMPLATE_attr(ir_node *node)
{
assert(is_TEMPLATE_irn(node) && "need TEMPLATE node to get attributes");
return (TEMPLATE_attr_t *)get_irn_generic_attr(node);
}
......@@ -203,23 +125,17 @@ TEMPLATE_attr_t *get_TEMPLATE_attr(ir_node *node) {
/**
* Returns the argument register requirements of a TEMPLATE node.
*/
const arch_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node) {
const arch_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node)
{
const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
return attr->in_req;
}
/**
* Returns the result register requirements of an TEMPLATE node.
*/
const arch_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node) {
const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
return attr->out_req;
}
/**
* Returns the argument register requirement at position pos of an TEMPLATE node.
*/
const arch_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos) {
const arch_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos)
{
const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
return attr->in_req[pos];
}
......@@ -227,23 +143,17 @@ const arch_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos) {
/**
* Returns the result register requirement at position pos of an TEMPLATE node.
*/
const arch_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos) {
const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
return attr->out_req[pos];
}
/**
* Sets the OUT register requirements at position pos.
*/
void set_TEMPLATE_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
attr->out_req[pos] = req;
const arch_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos)
{
const backend_info_t *info = be_get_info(node);
return info->out_infos[pos].req;
}
/**
* Sets the IN register requirements at position pos.
*/
void set_TEMPLATE_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
void set_TEMPLATE_req_in(ir_node *node, const arch_register_req_t *req, int pos)
{
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
attr->in_req[pos] = req;
}
......@@ -253,7 +163,6 @@ void set_TEMPLATE_req_in(ir_node *node, const arch_register_req_t *req, int pos)
*/
void init_TEMPLATE_attributes(ir_node *node, arch_irn_flags_t 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)
{
......@@ -264,7 +173,6 @@ void init_TEMPLATE_attributes(ir_node *node, arch_irn_flags_t flags,
(void) execution_units;
arch_irn_set_flags(node, flags);
attr->out_req = out_reqs;
attr->in_req = in_reqs;
info = be_get_info(node);
......@@ -282,8 +190,7 @@ void init_TEMPLATE_attributes(ir_node *node, arch_irn_flags_t flags,
*
***************************************************************************************/
static
int TEMPLATE_compare_attr(ir_node *a, ir_node *b)
static int TEMPLATE_compare_attr(ir_node *a, ir_node *b)
{
const TEMPLATE_attr_t *attr_a = get_TEMPLATE_attr_const(a);
const TEMPLATE_attr_t *attr_b = get_TEMPLATE_attr_const(b);
......
......@@ -50,11 +50,6 @@ const TEMPLATE_attr_t *get_TEMPLATE_attr_const(const ir_node *node);
*/
const arch_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node);
/**
* Returns the result register requirements of an TEMPLATE node.
*/
const arch_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node);
/**
* Returns the argument register requirements of an TEMPLATE node.
*/
......@@ -65,11 +60,6 @@ const arch_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos);
*/
const arch_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos);
/**
* Sets the OUT register requirements at position pos.
*/
void set_TEMPLATE_req_out(ir_node *node, const arch_register_req_t *req, int pos);
/**
* Sets the IN register requirements at position pos.
*/
......
......@@ -40,23 +40,10 @@
#include "TEMPLATE_nodes_attr.h"
#include "TEMPLATE_transform.h"
#include "TEMPLATE_new_nodes.h"
#include "TEMPLATE_map_regs.h"
#include "gen_TEMPLATE_regalloc_if.h"
extern ir_op *get_op_Mulh(void);
/****************************************************************************************************
* _ _ __ _ _
* | | | | / _| | | (_)
* _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
* | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
* | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
* |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
*
****************************************************************************************************/
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
/**
* Creates an TEMPLATE Add.
......@@ -66,7 +53,8 @@ extern ir_op *get_op_Mulh(void);
* @param op2 second operator
* @return the created TEMPLATE Add node
*/
static ir_node *gen_Add(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_Add(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
return new_bd_TEMPLATE_Add(env->dbg, env->block, op1, op2, env->mode);
}
......@@ -82,11 +70,11 @@ static ir_node *gen_Add(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op
* @param mode node mode
* @return the created TEMPLATE Mul node
*/
static ir_node *gen_Mul(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_Mul(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
if (mode_is_float(env->mode)) {
return new_bd_TEMPLATE_fMul(env->dbg, env->block, op1, op2, env->mode);
}
else {
} else {
return new_bd_TEMPLATE_Mul(env->dbg, env->block, op1, op2, env->mode);
}
}
......@@ -103,7 +91,8 @@ static ir_node *gen_Mul(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op
* @param mode node mode
* @return the created TEMPLATE And node
*/
static ir_node *gen_And(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_And(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
return new_bd_TEMPLATE_And(env->dbg, env->block, op1, op2, env->mode);
}
......@@ -119,7 +108,8 @@ static ir_node *gen_And(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op
* @param mode node mode
* @return the created TEMPLATE Or node
*/
static ir_node *gen_Or(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_Or(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
return new_bd_TEMPLATE_Or(env->dbg, env->block, op1, op2, env->mode);
}
......@@ -135,7 +125,8 @@ static ir_node *gen_Or(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2
* @param mode node mode
* @return the created TEMPLATE Eor node
*/
static ir_node *gen_Eor(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_Eor(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
return new_bd_TEMPLATE_Eor(env->dbg, env->block, op1, op2, env->mode);
}
......@@ -151,11 +142,11 @@ static ir_node *gen_Eor(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op
* @param mode node mode
* @return the created TEMPLATE Sub node
*/
static ir_node *gen_Sub(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_Sub(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
if (mode_is_float(env->mode)) {
return new_bd_TEMPLATE_fSub(env->dbg, env->block, op1, op2, env->mode);
}
else {
} else {
return new_bd_TEMPLATE_Sub(env->dbg, env->block, op1, op2, env->mode);
}
}
......@@ -172,7 +163,8 @@ static ir_node *gen_Sub(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op
* @param mode node mode
* @return the created TEMPLATE fDiv node
*/
static ir_node *gen_Quot(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_Quot(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
return new_bd_TEMPLATE_fDiv(env->dbg, env->block, op1, op2, env->mode);
}
......@@ -188,7 +180,8 @@ static ir_node *gen_Quot(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *o
* @param mode node mode
* @return the created TEMPLATE Shl node
*/
static ir_node *gen_Shl(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_Shl(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
return new_bd_TEMPLATE_Shl(env->dbg, env->block, op1, op2, env->mode);
}
......@@ -204,7 +197,8 @@ static ir_node *gen_Shl(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op
* @param mode node mode
* @return the created TEMPLATE Shr node
*/
static ir_node *gen_Shr(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
static ir_node *gen_Shr(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
{
return new_bd_TEMPLATE_Shr(env->dbg, env->block, op1, op2, env->mode);
}
......@@ -220,7 +214,8 @@ static ir_node *gen_Shr(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op
* @param mode node mode
* @return the created TEMPLATE Minus node
*/
static ir_node *gen_Minus(TEMPLATE_transform_env_t *env, ir_node *op) {
static ir_node *gen_Minus(TEMPLATE_transform_env_t *env, ir_node *op)
{
if (mode_is_float(env->mode)) {
return new_bd_TEMPLATE_fMinus(env->dbg, env->block, op, env->mode);
}
......@@ -239,7 +234,8 @@ static ir_node *gen_Minus(TEMPLATE_transform_env_t *env, ir_node *op) {
* @param mode node mode
* @return the created TEMPLATE Not node
*/
static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op) {
static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op)
{
return new_bd_TEMPLATE_Not(env->dbg, env->block, op, env->mode);
}
......@@ -254,7 +250,8 @@ static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op) {
* @param mode node mode
* @return the created TEMPLATE Load node
*/
static ir_node *gen_Load(TEMPLATE_transform_env_t *env) {
static ir_node *gen_Load(TEMPLATE_transform_env_t *env)
{
ir_node *node = env->irn;
if (mode_is_float(env->mode)) {
......@@ -274,7 +271,8 @@ static ir_node *gen_Load(TEMPLATE_transform_env_t *env) {
* @param mode node mode
* @return the created TEMPLATE Store node
*/
static ir_node *gen_Store(TEMPLATE_transform_env_t *env) {
static ir_node *gen_Store(TEMPLATE_transform_env_t *env)
{
ir_node *node = env->irn;
if (mode_is_float(env->mode)) {
......@@ -304,10 +302,8 @@ static ir_node *gen_Store(TEMPLATE_transform_env_t *env) {
* @param node the firm node
* @param env the debug module
*/
void TEMPLATE_transform_node(ir_node *node, void *env) {
#ifdef DEBUG_libfirm
TEMPLATE_code_gen_t *cgenv = (TEMPLATE_code_gen_t *)env;
#endif
void TEMPLATE_transform_node(ir_node *node, void *env)
{
ir_opcode code = get_irn_opcode(node);
ir_node *asm_node = NULL;
TEMPLATE_transform_env_t tenv;
......@@ -320,9 +316,6 @@ void TEMPLATE_transform_node(ir_node *node, void *env) {
tenv.dbg = get_irn_dbg_info(node);
tenv.irg = current_ir_graph;
tenv.irn = node;
#ifdef DEBUG_libfirm
tenv.mod = cgenv->mod;
#endif
tenv.mode = get_irn_mode(node);
#define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
......@@ -331,7 +324,7 @@ void TEMPLATE_transform_node(ir_node *node, void *env) {
#define IGN(a) case iro_##a: break
#define BAD(a) case iro_##a: goto bad
DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
DBG((dbg, LEVEL_1, "check %+F ... ", node));
switch (code) {
BINOP(Add);
......@@ -407,9 +400,14 @@ bad:
if (asm_node) {
exchange(node, asm_node);