Commit 323267da authored by Christian Würdig's avatar Christian Würdig
Browse files

added support for separate outflags

parent 9d9b738c
......@@ -265,37 +265,19 @@ static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
}
static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
arch_irn_flags_t flags = arch_irn_flags_none;
if(is_Proj(irn)) {
ir_node *pred = get_Proj_pred(irn);
int ia32_op = get_ia32_irn_opcode(pred);
long proj = get_Proj_proj(irn);
if (iro_ia32_Push == ia32_op && proj == pn_ia32_Push_stack) {
/* Push modifies always ESP, this cannot be changed */
return arch_irn_flags_modify_sp | arch_irn_flags_ignore;
}
if (iro_ia32_Pop == ia32_op && proj == pn_ia32_Pop_stack) {
/* Pop modifies always ESP, this cannot be changed */
return arch_irn_flags_modify_sp | arch_irn_flags_ignore;
}
if (iro_ia32_AddSP == ia32_op && proj == pn_ia32_AddSP_stack) {
/* AddSP modifies always ESP, this cannot be changed */
return arch_irn_flags_modify_sp | arch_irn_flags_ignore;
}
if (iro_ia32_SubSP == ia32_op && proj == pn_ia32_SubSP_stack) {
/* SubSP modifies always ESP, this cannot be changed */
return arch_irn_flags_modify_sp | arch_irn_flags_ignore;
}
if (is_Proj(irn) && is_ia32_irn(get_Proj_pred(irn))) {
flags |= get_ia32_out_flags(irn, get_Proj_proj(irn));
}
irn = skip_Proj(irn);
if (is_ia32_irn(irn))
return get_ia32_flags(irn);
else {
if (is_Unknown(irn))
return arch_irn_flags_ignore;
return 0;
}
flags |= get_ia32_flags(irn);
else if (is_Unknown(irn))
flags = arch_irn_flags_ignore;
return flags;
}
/**
......
......@@ -1075,6 +1075,24 @@ void set_ia32_pncode(ir_node *node, long code) {
attr->pn_code = code;
}
/**
* Sets the flags for the n'th out.
*/
void set_ia32_out_flags(ir_node *node, arch_irn_flags_t flags, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
attr->out_flags[pos] = flags;
}
/**
* Gets the flags for the n'th out.
*/
arch_irn_flags_t get_ia32_out_flags(const ir_node *node, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
return attr->out_flags[pos];
}
#ifndef NDEBUG
/**
......@@ -1288,7 +1306,6 @@ int is_ia32_Cnst(const ir_node *node) {
const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
assert(is_ia32_irn(node) && "Not an ia32 node.");
assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
assert(attr->slots[pos] && "No register assigned");
......@@ -1301,7 +1318,6 @@ const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
int get_ia32_out_regnr(const ir_node *node, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
assert(is_ia32_irn(node) && "Not an ia32 node.");
assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
assert(attr->slots[pos] && "No register assigned");
......@@ -1314,7 +1330,6 @@ int get_ia32_out_regnr(const ir_node *node, int pos) {
const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
ia32_attr_t *attr = get_ia32_attr(node);
assert(is_ia32_irn(node) && "Not an ia32 node.");
assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
assert(attr->slots[pos] && "No register assigned");
......@@ -1333,6 +1348,9 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_regi
set_ia32_out_req_all(node, out_reqs);
set_ia32_latency(node, latency);
attr->out_flags = NEW_ARR_D(int, get_irg_obstack(get_irn_irg(node)), n_res);
memset(attr->out_flags, 0, n_res * sizeof(attr->out_flags[0]));
attr->data.n_res = n_res;
memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0]));
}
......
......@@ -393,6 +393,17 @@ unsigned get_ia32_latency(const ir_node *node);
*/
void set_ia32_latency(ir_node *node, unsigned latency);
/**
* Sets the flags for the n'th out.
*/
void set_ia32_out_flags(ir_node *node, arch_irn_flags_t flags, int pos);
/**
* Gets the flags for the n'th out.
*/
arch_irn_flags_t get_ia32_out_flags(const ir_node *node, int pos);
#ifndef NDEBUG
/**
......
......@@ -88,7 +88,7 @@ typedef struct _ia32_attr_t {
unsigned op_flav:2; /**< flavour of an op (flavour_Div/Mod/DivMod) */
unsigned flags:4; /**< indicating if spillable and/or rematerializeable */
unsigned flags:4; /**< indicating if spillable, rematerializeable, stack modifying and/or ignore */
unsigned is_commutative:1; /**< indicates whether op is commutative or not */
......@@ -101,6 +101,8 @@ typedef struct _ia32_attr_t {
unsigned n_res:6; /**< number of results produced by this node */
} data;
int *out_flags; /**< flags for each produced value */
int am_offs; /**< offsets for AddrMode */
ident *am_sc; /**< SymConst for AddrMode */
......
......@@ -73,6 +73,10 @@ $comment_string = "/*";
#
# outs: if a node defines more than one output, the names of the projections
# nodes having outs having automatically the mode mode_T
# One can also annotate some flags for each out, additional to irn_flags.
# They are separated from name with a colon ':', and concatenated by pipe '|'
# Only I and S are available at the moment (same meaning as in irn_flags).
# example: [ "frame:I", "stack:I|S", "M" ]
#
# comment: OPTIONAL comment for the node constructor
#
......@@ -716,11 +720,10 @@ else {
},
"Push" => {
# We don't set class modify_stack here (but we will do this on proj 0)
"comment" => "push on the stack",
"reg_req" => { "in" => [ "gp", "gp", "gp", "esp", "none" ], "out" => [ "esp" ] },
"emit" => '. push %ia32_emit_unop /* PUSH(%A1) */',
"outs" => [ "stack", "M" ],
"outs" => [ "stack:I|S", "M" ],
"latency" => 3,
},
......@@ -729,7 +732,7 @@ else {
"comment" => "pop a gp register from the stack",
"reg_req" => { "in" => [ "gp", "gp", "esp", "none" ], "out" => [ "gp", "esp" ] },
"emit" => '. pop %ia32_emit_unop /* POP(%A1) */',
"outs" => [ "res", "stack", "M" ],
"outs" => [ "res", "stack:I|S", "M" ],
"latency" => 4,
},
......@@ -737,7 +740,7 @@ else {
"comment" => "create stack frame",
"reg_req" => { "in" => [ "esp" ], "out" => [ "ebp", "esp" ] },
"emit" => '. enter /* Enter */',
"outs" => [ "frame", "stack", "M" ],
"outs" => [ "frame:I", "stack:I|S", "M" ],
"latency" => 15,
},
......@@ -745,7 +748,7 @@ else {
"comment" => "destroy stack frame",
"reg_req" => { "in" => [ "esp", "ebp" ], "out" => [ "ebp", "esp" ] },
"emit" => '. leave /* Leave */',
"outs" => [ "frame", "stack", "M" ],
"outs" => [ "frame:I", "stack:I|S", "M" ],
"latency" => 3,
},
......@@ -753,14 +756,14 @@ else {
"irn_flags" => "I",
"comment" => "allocate space on stack",
"reg_req" => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] },
"outs" => [ "stack", "M" ],
"outs" => [ "stack:S", "M" ],
},
"SubSP" => {
"irn_flags" => "I",
"comment" => "free space on stack",
"reg_req" => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] },
"outs" => [ "stack", "M" ],
"outs" => [ "stack:S", "M" ],
},
"LdTls" => {
......
......@@ -61,9 +61,11 @@ push(@obst_header, "void ".$arch."_create_opcodes(void);\n");
push(@obst_enum_op, "typedef enum _$arch\_opcodes {\n");
foreach my $op (keys(%nodes)) {
my %n = %{ $nodes{"$op"} };
my $tuple = 0;
my $n_res = 0;
my %n = %{ $nodes{"$op"} };
my $tuple = 0;
my $n_res = 0;
my $num_outs = 0;
my @out_flags;
# determine arity from in requirements
$arity = exists($n{"arity"}) ? $n{"arity"} : 0;
......@@ -75,13 +77,24 @@ foreach my $op (keys(%nodes)) {
$op = $arch."_".$op;
$temp = "";
# define some proj numbers
if (exists($n{"outs"})) {
undef my @outs;
@outs = @{ $n{"outs"} };
@outs = @{ $n{"outs"} };
$num_outs = $#outs;
push(@obst_proj, "\nenum pn_$op {\n");
for (my $idx = 0; $idx <= $#outs; $idx++) {
# check, if we have additional flags annotated to out
if ($outs[$idx] =~ /:(S|I(\|(S|I))*)/) {
push(@out_flags, $1);
$outs[$idx] =~ s/:(S|I(\|(S|I))*)//;
}
push(@obst_proj, " pn_$op\_".$outs[$idx]." = $idx,\n");
}
push(@obst_proj, "};\n");
$tuple = 1;
}
......@@ -276,6 +289,29 @@ foreach my $op (keys(%nodes)) {
$temp .= "\n /* init node attributes */\n";
$temp .= " init_$arch\_attributes(res, flags, $in_param, $out_param, $latency);\n";
# set flags for outs
if ($#out_flags >= 0) {
$temp .= "\n /* 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 = " | ";
}
elsif ($flag eq "S") {
$flags .= $prefix."arch_irn_flags_modify_sp";
$prefix = " | ";
}
}
$temp .= " set_$arch\_out_flags(res, $flags, $idx);\n";
}
}
if (exists($n{"init_attr"})) {
$temp .= " attr = get_$arch\_attr(res);\n";
$temp .= $n{"init_attr"}."\n";
......
Supports Markdown
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