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

- Add a generic_attribute field to irops

- extend backend generator to support custom irop data
- cleanup and streamline transform code in ia32
- Improve handling of AddAM vs. Add used in AM expressions

[r16254]
parent 33445ede
......@@ -367,13 +367,12 @@ 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, unsigned latency)
int n_res)
{
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
(void) execution_units;
(void) latency;
attr->flags = flags;
attr->out_req = out_reqs;
......
......@@ -535,12 +535,11 @@ static void init_arm_attributes(ir_node *node, int 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, unsigned latency) {
int n_res) {
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
arm_attr_t *attr = get_arm_attr(node);
(void) execution_units;
(void) latency;
attr->in_req = in_reqs;
attr->out_req = out_reqs;
......
......@@ -179,10 +179,10 @@ $default_attr_type = "arm_attr_t";
$default_copy_attr = "arm_copy_attr";
%init_attr = (
arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
arm_SymConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
arm_SymConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
);
%compare_attr = (
......
......@@ -312,7 +312,7 @@ static void displace(belady_env_t *env, workset_t *new_vals, int is_usage) {
assert(is_usage);
}
}
DBG((dbg, DBG_DECIDE, " demand = %d\n", demand));
//DBG((dbg, DBG_DECIDE, " demand = %d\n", demand));
/*
2. Make room for at least 'demand' slots
......@@ -320,10 +320,10 @@ static void displace(belady_env_t *env, workset_t *new_vals, int is_usage) {
len = workset_get_length(ws);
max_allowed = env->n_regs - demand;
DBG((dbg, DBG_DECIDE, " disposing %d values\n", ws->len - max_allowed));
/* Only make more free room if we do not have enough */
if (len > max_allowed) {
DBG((dbg, DBG_DECIDE, " disposing %d values\n", ws->len - max_allowed));
/* get current next-use distance */
for (i = 0; i < ws->len; ++i) {
unsigned dist = get_distance(env, env->instr, env->instr_nr, workset_get_val(ws, i), !is_usage);
......
......@@ -60,6 +60,10 @@ void be_set_transformed_node(ir_node *old_node, ir_node *new_node) {
set_irn_link(old_node, new_node);
}
int be_is_transformed(const ir_node *node) {
return irn_visited(node);
}
static INLINE ir_node *be_get_transformed_node(ir_node *old_node) {
assert(irn_visited(old_node));
return (ir_node*) get_irn_link(old_node);
......
......@@ -68,6 +68,11 @@ ir_node *be_duplicate_node(ir_node *node);
*/
void be_set_transformed_node(ir_node *old_node, ir_node *new_node);
/**
* returns 1 if the node is already transformed
*/
int be_is_transformed(const ir_node *node);
/**
* enqueue all inputs into the transform queue.
*/
......
......@@ -1346,7 +1346,7 @@ static void transform_MemPerm(ia32_code_gen_t *cg, ir_node *node) {
}
in[0] = sp;
keep = be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in);
keep = be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in);
sched_add_before(node, keep);
// exchange memprojs
......
......@@ -420,6 +420,10 @@ void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force)
addr->base = node;
}
void ia32_mark_non_am(ir_node *node)
{
bitset_set(non_address_mode_nodes, get_irn_idx(node));
}
/**
* Walker: mark those nodes that cannot be part of an address mode because
......@@ -433,8 +437,13 @@ static void mark_non_address_nodes(ir_node *node, void *env)
ir_node *val;
ir_node *left;
ir_node *right;
ir_mode *mode;
(void) env;
mode = get_irn_mode(node);
if(!mode_is_int(mode) && !mode_is_reference(mode) && mode != mode_b)
return;
switch(get_irn_opcode(node)) {
case iro_Load:
ptr = get_Load_ptr(node);
......@@ -455,15 +464,19 @@ static void mark_non_address_nodes(ir_node *node, void *env)
case iro_Add:
left = get_Add_left(node);
right = get_Add_right(node);
#if 0
/* if we can do source address mode then we will never fold the add
* into address mode */
if(!mode_is_float(get_irn_mode(node)) && (is_immediate_simple(right) ||
if((is_immediate_simple(right)) ||
(!ia32_use_source_address_mode(get_nodes_block(node), left, right)
&& !ia32_use_source_address_mode(get_nodes_block(node), right, left))))
&& !ia32_use_source_address_mode(get_nodes_block(node), right, left)))
{
break;
}
bitset_set(non_address_mode_nodes, get_irn_idx(node));
#else
break;
#endif
/* fallthrough */
default:
......@@ -477,14 +490,14 @@ static void mark_non_address_nodes(ir_node *node, void *env)
}
}
void calculate_non_address_mode_nodes(ir_graph *irg)
void ia32_calculate_non_address_mode_nodes(ir_graph *irg)
{
non_address_mode_nodes = bitset_malloc(get_irg_last_idx(irg));
irg_walk_graph(irg, NULL, mark_non_address_nodes, NULL);
}
void free_non_address_mode_nodes(void)
void ia32_free_non_address_mode_nodes(void)
{
bitset_free(non_address_mode_nodes);
}
......@@ -54,11 +54,16 @@ void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force);
* Mark those nodes of the given graph that cannot be used inside an
* address mode because there values must be materialized in registers.
*/
void calculate_non_address_mode_nodes(ir_graph *irg);
void ia32_calculate_non_address_mode_nodes(ir_graph *irg);
/**
* Free the non_address_mode information.
*/
void free_non_address_mode_nodes(void);
void ia32_free_non_address_mode_nodes(void);
/**
* mark a node so it will not be used as part of address modes
*/
void ia32_mark_non_am(ir_node *node);
#endif
......@@ -684,16 +684,9 @@ void set_ia32_frame_ent(ir_node *node, ir_entity *ent) {
* Gets the instruction latency.
*/
unsigned get_ia32_latency(const ir_node *node) {
const ia32_attr_t *attr = get_ia32_attr_const(node);
return attr->latency;
}
/**
* Sets the instruction latency.
*/
void set_ia32_latency(ir_node *node, unsigned latency) {
ia32_attr_t *attr = get_ia32_attr(node);
attr->latency = latency;
const ir_op *op = get_irn_op(node);
const ia32_op_attr_t *op_attr = (ia32_op_attr_t*) get_op_attr(op);
return op_attr->latency;
}
/**
......@@ -993,7 +986,7 @@ void init_ia32_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, unsigned latency)
int n_res)
{
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
......@@ -1002,7 +995,6 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
set_ia32_flags(node, flags);
set_ia32_in_req_all(node, in_reqs);
set_ia32_out_req_all(node, out_reqs);
set_ia32_latency(node, latency);
attr->exec_units = execution_units;
#ifndef NDEBUG
......
......@@ -47,7 +47,9 @@ enum {
enum {
pn_ia32_res = 0,
pn_ia32_mem = 1,
pn_ia32_flags = 2
pn_ia32_flags = 2,
pn_ia32_add1 = 3,
pn_ia32_add2 = 4
};
/***************************************************************************************************
......@@ -324,11 +326,6 @@ unsigned get_ia32_copyb_size(const ir_node *node);
*/
unsigned get_ia32_latency(const ir_node *node);
/**
* Sets the instruction latency.
*/
void set_ia32_latency(ir_node *node, unsigned latency);
/**
* Sets the flags for the n'th out.
......@@ -432,7 +429,7 @@ void init_ia32_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, unsigned latency);
int n_res);
void init_ia32_x87_attributes(ir_node *node);
void init_ia32_asm_attributes(ir_node *node);
......
......@@ -53,18 +53,27 @@ typedef enum {
ia32_am_ternary = 3,
} ia32_am_arity_t;
/**
* Different Address Mode properties:
* O - Offset is set
* B - Base is set
* I - Index is set
* S - Scale is set
*/
enum {
ia32_O = (1 << 0), /**< O - Offset is set */
ia32_B = (1 << 1), /**< B - Base is set */
ia32_I = (1 << 2), /**< I - Index is set */
ia32_S = (1 << 3) /**< S - Scale is set */
typedef enum {
match_commutative = 1 << 0, /**< inputs are commutative */
match_am_and_immediates = 1 << 1, /**< mode support AM and immediate at
the same time */
match_am = 1 << 2, /**< node supports (32bit) source AM */
match_8bit_am = 1 << 3, /**< node supports 8bit source AM */
match_16bit_am = 1 << 4, /**< node supports 16bit source AM */
match_immediate = 1 << 5, /**< node supports immediates */
match_8bit = 1 << 6, /**< supports 8 bit modes natively */
match_16bit = 1 << 7, /**< supports 16bit modes natively */
match_mode_neutral = 1 << 8, /**< 16 and 8 bit modes can be emulated
by 32 bit operations */
match_dest_am = 1 << 9,
match_try_am = 1 << 10, /**< only try to produce AM node, don't
do anything if AM isn't possible */
} match_flags_t;
typedef struct ia32_op_attr_t ia32_op_attr_t;
struct ia32_op_attr_t {
match_flags_t flags;
unsigned latency;
};
#ifndef NDEBUG
......@@ -116,8 +125,6 @@ struct ia32_attr_t {
ir_entity *frame_ent; /**< the frame entity attached to this node */
unsigned latency; /**< the latency of the instruction in clock cycles */
const be_execution_unit_t ***exec_units; /**< list of units this operation can be executed on */
const arch_register_req_t **in_req; /**< register requirements for arguments */
......
......@@ -6,6 +6,7 @@
# |____/____/|_____| \_/ \___|\___|\__\___/|_| |_| |_|\___/ \__,_|\___||___/
$nodes{"mov_gp_variant0"} = {
"reg_req" => { "in" => [ "xmm", ], "out" => [ "gp", ] },
"emit" => ". shl %S2, 15; .movd %S1, %S2",
reg_req => { "in" => [ "xmm", ], "out" => [ "gp", ] },
emit => ". shl %S2, 15; .movd %S1, %S2",
latency => 3,
};
This diff is collapsed.
This diff is collapsed.
......@@ -393,13 +393,12 @@ static void init_mips_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, unsigned latency)
int n_res)
{
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
mips_attr_t *attr = get_mips_attr(node);
(void) execution_units;
(void) latency;
attr->flags = flags;
attr->out_req = out_reqs;
......
......@@ -148,12 +148,12 @@ $default_copy_attr = "mips_copy_attr";
$mode_gp = "mode_Iu";
%init_attr = (
mips_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
mips_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
mips_immediate_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
mips_immediate_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
"\tinit_mips_immediate_attributes(res, imm_type, entity, val);",
mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
"\tinit_mips_load_store_attributes(res, entity, offset);",
);
......
......@@ -496,12 +496,11 @@ ppc32_attr_offset_mode get_ppc32_offset_mode(const ir_node *node) {
void init_ppc32_attributes(ir_node *node, int 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, unsigned latency) {
int n_res) {
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
ppc32_attr_t *attr = get_ppc32_attr(node);
(void) execution_units;
(void) latency;
attr->flags = flags;
attr->in_req = in_reqs;
......
......@@ -132,11 +132,6 @@ int get_ppc32_offset(const ir_node *node);
void set_ppc32_offset_mode(const ir_node *node, ppc32_attr_offset_mode mode);
ppc32_attr_offset_mode get_ppc32_offset_mode(const ir_node *node);
void init_ppc32_attributes(ir_node *node, int 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, unsigned latency);
void ppc32_register_additional_opcodes(int opcode_num);
/* Include the generated headers */
......
......@@ -39,6 +39,7 @@ our $additional_opcodes;
our %nodes;
our %operands;
our %cpu;
our $default_op_attr_type;
our $default_attr_type;
our $default_cmp_attr;
our $default_copy_attr;
......@@ -68,7 +69,7 @@ if(!defined($default_attr_type)) {
}
if(!defined(%init_attr)) {
%init_attr = (
"$default_attr_type" => "\tinit_${arch}_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
"$default_attr_type" => "\tinit_${arch}_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
);
}
if(!defined($default_cmp_attr)) {
......@@ -376,12 +377,6 @@ foreach my $op (keys(%nodes)) {
$temp .= "\tint n_res = ${out_arity};\n";
}
my $latency = $n{"latency"};
if (!defined($latency)) {
$latency = 1;
}
$temp .= "\tunsigned latency = ${latency};\n";
if (defined($known_mode)) {
$temp .= "\tir_mode *mode = ${known_mode};\n";
}
......@@ -513,29 +508,32 @@ foreach my $op (keys(%nodes)) {
$temp .= "\n";
# set flags for outs
if ($#out_flags >= 0) {
$temp .= "\t/* set flags for outs */\n";
for (my $idx = 0; $idx <= $#out_flags; $idx++) {
my $flags = "";
my $prefix = "";
foreach my $flag (split(/\|/, $out_flags[$idx])) {
if ($flag eq "I") {
$flags .= $prefix."arch_irn_flags_ignore";
$prefix = " | ";
if (exists($n{"outs"})) {
undef my @outs;
@outs = @{ $n{"outs"} };
for (my $idx = 0; $idx <= $#outs; $idx++) {
# check, if we have additional flags annotated to out
if ($outs[$idx] =~ /:((S|I)(\|(S|I))*)/) {
my $flag_string = $1;
my $prefix = "";
my $flags = "";
foreach my $flag (split(/\|/, $flag_string)) {
if ($flag eq "I") {
$flags .= $prefix."arch_irn_flags_ignore";
$prefix = " | ";
} elsif ($flag eq "S") {
$flags .= $prefix."arch_irn_flags_modify_sp";
$prefix = " | ";
}
}
elsif ($flag eq "S") {
$flags .= $prefix."arch_irn_flags_modify_sp";
$prefix = " | ";
}
}
$temp .= "\tset_$arch\_out_flags(res, $flags, $idx);\n";
$temp .= "\tset_$arch\_out_flags(res, $flags, $idx);\n";
}
}
$temp .= "\n";
}
if (exists($n{"init_attr"})) {
$temp .= "\tattr = get_irn_generic_attr(res);\n";
$temp .= "\t".$n{"init_attr"}."\n";
......@@ -586,6 +584,15 @@ foreach my $op (keys(%nodes)) {
$temp .= "|M, ".translate_arity($arity).", 0, sizeof(${attr_type}), &ops);\n";
push(@obst_new_irop, $temp);
push(@obst_new_irop, "\tset_op_tag(op_$op, &$arch\_op_tag);\n");
if(defined($default_op_attr_type)) {
push(@obst_new_irop, "\tattr = ($default_op_attr_type *) xmalloc(sizeof(attr[0]));\n");
push(@obst_new_irop, "\tmemset(attr, 0, sizeof(attr[0]));\n");
if(defined($n{op_attr_init})) {
push(@obst_new_irop, "\t".$n{op_attr_init}."\n");
}
push(@obst_new_irop, "\tset_op_attr(op_$op, attr);\n");
}
push(@obst_enum_op, "\tiro_$op,\n");
push(@obst_header, "\n");
......@@ -706,6 +713,13 @@ void $arch\_create_opcodes(void) {
ir_op_ops ops;
int cur_opcode;
static int run_once = 0;
ENDOFMAIN
if(defined($default_op_attr_type)) {
print OUT "\t$default_op_attr_type *attr;\n";
}
print OUT<<ENDOFMAIN;
if (run_once)
return;
......
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