Commit 9fcd5f66 authored by Christoph Mallon's avatar Christoph Mallon
Browse files

Allow two should-be-same constraints for every out register. This is useful...

Allow two should-be-same constraints for every out register. This is useful for commutative nodes on two address code machines (i.e. x86).

[r15953]
parent 8a45e869
......@@ -91,7 +91,9 @@ static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
}
if (reqs[i]->type & arch_register_req_type_should_be_same) {
ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same[0]));
if (reqs[i]->other_same[1] != -1)
ir_fprintf(F, " or %+F", get_irn_n(n, reqs[i]->other_same[1]));
}
if (reqs[i]->type & arch_register_req_type_should_be_different) {
......
......@@ -100,7 +100,9 @@ static void dump_reg_req(FILE *F, const ir_node *node,
}
if (reqs[i]->type & arch_register_req_type_should_be_same) {
ir_fprintf(F, " same as %+F", get_irn_n(node, reqs[i]->other_same));
ir_fprintf(F, " same as %+F", get_irn_n(node, reqs[i]->other_same[0]));
if (reqs[i]->other_same[1] != -1)
ir_fprintf(F, " or %+F", get_irn_n(node, reqs[i]->other_same[1]));
}
if (reqs[i]->type & arch_register_req_type_should_be_different) {
......
......@@ -333,9 +333,14 @@ extern char *arch_register_req_format(char *buf, size_t len,
}
if(arch_register_req_is(req, should_be_same)) {
const ir_node *same = get_irn_n(skip_Proj_const(node), req->other_same);
const ir_node *same = get_irn_n(skip_Proj_const(node), req->other_same[0]);
ir_snprintf(tmp, sizeof(tmp), " same to: %+F", same);
strncat(buf, tmp, len);
if (req->other_same[1] != -1) {
const ir_node *same2 = get_irn_n(skip_Proj_const(node), req->other_same[1]);
ir_snprintf(tmp, sizeof(tmp), "or %+F", same2);
strncat(buf, tmp, len);
}
}
if(arch_register_req_is(req, should_be_different)) {
......
......@@ -128,8 +128,11 @@ struct arch_register_req_t {
const unsigned *limited; /**< allowed register bitset */
int other_same; /**< The in number which shall have
the same res (should_be_same)*/
int other_same[2]; /**< The in numbers which shall have the
same res (should_be_same). More than
two are unnecessary because there is
no machine with more than two
commutative inputs to one operation */
int other_different; /**< The other node from which this
one's register must be different
(case must_be_different). */
......
......@@ -462,7 +462,7 @@ static void co_collect_units(ir_node *irn, void *env) {
/* Src == Tgt of a 2-addr-code instruction */
if (is_2addr_code(req)) {
ir_node *other = get_irn_n(skip_Proj(irn), req->other_same);
ir_node *other = get_irn_n(skip_Proj(irn), req->other_same[0]); /* TODO handle second should-be-same constraint */
if (!arch_irn_is(co->aenv, other, ignore) &&
!nodes_interfere(co->cenv, irn, other)) {
unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
......@@ -765,27 +765,29 @@ static void build_graph_walker(ir_node *irn, void *env) {
if (arch_register_type_is(reg, ignore))
return;
/* Phis */
if (is_Reg_Phi(irn))
if (is_Reg_Phi(irn)) { /* Phis */
for (pos=0, max=get_irn_arity(irn); pos<max; ++pos) {
ir_node *arg = get_irn_n(irn, pos);
add_edges(co, irn, arg, co->get_costs(co, irn, arg, pos));
}
/* Perms */
else if (is_Perm_Proj(co->aenv, irn)) {
}
else if (is_Perm_Proj(co->aenv, irn)) { /* Perms */
ir_node *arg = get_Perm_src(irn);
add_edges(co, irn, arg, co->get_costs(co, irn, arg, 0));
}
/* 2-address code */
else {
const arch_register_req_t *req =
arch_get_register_req(co->aenv, irn, -1);
else { /* 2-address code */
const arch_register_req_t *req = arch_get_register_req(co->aenv, irn, -1);
if (is_2addr_code(req)) {
ir_node *other = get_irn_n(skip_Proj(irn), req->other_same);
if (! arch_irn_is(co->aenv, other, ignore))
add_edges(co, irn, other, co->get_costs(co, irn, other, 0));
const int *i;
for (i = req->other_same; i != ENDOF(req->other_same); ++i) {
ir_node *other;
if (*i == -1) break;
other = get_irn_n(skip_Proj(irn), *i);
if (! arch_irn_is(co->aenv, other, ignore))
add_edges(co, irn, other, co->get_costs(co, irn, other, 0));
}
}
}
}
......
......@@ -546,7 +546,8 @@ ir_node *be_new_Copy(const arch_register_class_t *cls, ir_graph *irg, ir_node *b
req = get_req(res, OUT_POS(0));
req->cls = cls;
req->type = arch_register_req_type_should_be_same;
req->other_same = 0;
req->other_same[0] = 0;
req->other_same[1] = -1;
return res;
}
......
......@@ -427,13 +427,18 @@ static void dump_affinities_walker(ir_node *irn, void *env) {
/* should_be_equal constraints are affinites */
for (pos = 0, max = get_irn_arity(irn); pos<max; ++pos) {
req = arch_get_register_req(raenv->aenv, irn, pos);
if (arch_register_req_is(req, should_be_same)) {
ir_node *other = get_irn_n(skip_Proj(irn), req->other_same);
if(arch_irn_is(raenv->aenv, other, ignore)) {
vi2 = be_get_var_info(other);
const int* i;
for (i = req->other_same; i != ENDOF(req->other_same); ++i) {
ir_node *other;
if (*i == -1) break;
fprintf(raenv->f, "(%d, %d, %d)\n", vi1->var_nr, vi2->var_nr, get_affinity_weight(irn));
other = get_irn_n(skip_Proj(irn), *i);
if(arch_irn_is(raenv->aenv, other, ignore)) {
vi2 = be_get_var_info(other);
fprintf(raenv->f, "(%d, %d, %d)\n", vi1->var_nr, vi2->var_nr, get_affinity_weight(irn));
}
}
}
}
......
......@@ -401,7 +401,7 @@ static void assure_should_be_same_requirements(ia32_code_gen_t *cg,
if (!arch_register_req_is(req, should_be_same))
continue;
same_pos = req->other_same;
same_pos = req->other_same[0];
/* get in and out register */
out_reg = get_ia32_out_reg(node, i);
......@@ -543,7 +543,7 @@ static void fix_am_source(ir_node *irn, void *env) {
if (arch_register_req_is(reqs[i], should_be_same)) {
/* get in and out register */
const arch_register_t *out_reg = get_ia32_out_reg(irn, i);
int same_pos = reqs[i]->other_same;
int same_pos = reqs[i]->other_same[0];
ir_node *same_node = get_irn_n(irn, same_pos);
const arch_register_t *same_reg
= arch_get_irn_register(arch_env, same_node);
......
......@@ -96,7 +96,9 @@ static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
}
if (reqs[i]->type & arch_register_req_type_should_be_same) {
ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same[0]));
if (reqs[i]->other_same[1] != -1)
ir_fprintf(F, " or %+F", get_irn_n(n, reqs[i]->other_same[1]));
}
if (reqs[i]->type & arch_register_req_type_should_be_different) {
......
......@@ -364,7 +364,7 @@ ProduceVal => {
Add => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4", "none", "flags" ] },
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5", "none", "flags" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. add%M %binop',
am => "full,binary",
......@@ -394,7 +394,7 @@ AddMem8Bit => {
},
Adc => {
reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right", "eflags" ],
emit => '. adc%M %binop',
am => "full,binary",
......@@ -438,7 +438,7 @@ l_Mul => {
IMul => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. imul%M %binop',
am => "source,binary",
......@@ -471,7 +471,7 @@ l_IMul => {
And => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
am => "full,binary",
emit => '. and%M %binop',
......@@ -502,7 +502,7 @@ AndMem8Bit => {
Or => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
am => "full,binary",
emit => '. or%M %binop',
......@@ -533,7 +533,7 @@ OrMem8Bit => {
Xor => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
am => "full,binary",
emit => '. xor%M %binop',
......@@ -1339,7 +1339,7 @@ xZero => {
xAdd => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. add%XXM %binop',
latency => 4,
......@@ -1349,7 +1349,7 @@ xAdd => {
xMul => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. mul%XXM %binop',
latency => 4,
......@@ -1359,7 +1359,7 @@ xMul => {
xMax => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. max%XXM %binop',
latency => 2,
......@@ -1369,7 +1369,7 @@ xMax => {
xMin => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. min%XXM %binop',
latency => 2,
......@@ -1379,7 +1379,7 @@ xMin => {
xAnd => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. andp%XSD %binop',
latency => 3,
......@@ -1389,7 +1389,7 @@ xAnd => {
xOr => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. orp%XSD %binop',
units => [ "SSE" ],
......@@ -1398,7 +1398,7 @@ xOr => {
xXor => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
ins => [ "base", "index", "mem", "left", "right" ],
emit => '. xorp%XSD %binop',
latency => 3,
......
......@@ -3087,7 +3087,8 @@ void parse_asm_constraint(int pos, constraint_t *constraint, const char *c)
req->cls = other_constr->cls;
req->type = arch_register_req_type_should_be_same;
req->limited = NULL;
req->other_same = pos;
req->other_same[0] = pos;
req->other_same[1] = -1;
req->other_different = -1;
/* switch constraints. This is because in firm we have same_as
......
......@@ -94,7 +94,9 @@ static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
}
if (reqs[i]->type & arch_register_req_type_should_be_same) {
ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same[0]));
if (reqs[i]->other_same[1] != -1)
ir_fprintf(F, " or %+F", get_irn_n(n, reqs[i]->other_same[1]));
}
if (reqs[i]->type & arch_register_req_type_should_be_different) {
......
......@@ -91,7 +91,9 @@ static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
}
if (reqs[i]->type & arch_register_req_type_should_be_same) {
ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same[0]));
if (reqs[i]->other_same[1] != -1)
ir_fprintf(F, " or %+F", get_irn_n(n, reqs[i]->other_same[1]));
}
if (reqs[i]->type & arch_register_req_type_should_be_different) {
......
......@@ -963,6 +963,7 @@ sub build_subset_class_func {
my $has_limit = 0;
my $limit_name;
my $same_pos = undef;
my $same_pos2 = undef;
my $different_pos = undef;
my $temp;
my @obst_init;
......@@ -985,22 +986,26 @@ sub build_subset_class_func {
# set/unset registers
CHECK_REQS: foreach (@regs) {
if (/(!)?$outin\_r(\d+)/) {
if (($1 && defined($different_pos)) || (!$1 && defined($same_pos))) {
if (($1 && defined($different_pos)) || (!$1 && defined($same_pos2))) {
print STDERR "Multiple in/out references of same type in one requirement not allowed.\n";
return (undef, undef, undef, undef);
return (undef, undef, undef, undef, undef);
}
if ($1) {
$different_pos = $is_in ? -$2 : $2 - 1;
} else {
$same_pos = $is_in ? -$2 : $2 - 1;
if (!defined($same_pos)) {
$same_pos = $is_in ? -$2 : $2 - 1;
} else {
$same_pos2 = $is_in ? -$2 : $2 - 1;
}
}
$class = $idx_class[$2 - 1];
next CHECK_REQS;
} elsif (/!in/) {
$class = $idx_class[0];
return ($class, "NULL", undef, 666);
return ($class, "NULL", undef, undef, 666);
}
# check for negate
......@@ -1009,7 +1014,7 @@ CHECK_REQS: foreach (@regs) {
# we have seen a positiv constraint as first one but this one is negative
# this doesn't make sense
print STDERR "Mixed positive and negative constraints for the same slot are not allowed.\n";
return (undef, undef, undef, undef);
return (undef, undef, undef, undef, undef);
}
if (!defined($neg)) {
......@@ -1023,7 +1028,7 @@ CHECK_REQS: foreach (@regs) {
# we have seen a negative constraint as first one but this one is positive
# this doesn't make sense
print STDERR "Mixed positive and negative constraints for the same slot are not allowed.\n";
return (undef, undef, undef, undef);
return (undef, undef, undef, undef, undef);
}
$has_limit = 1;
......@@ -1034,7 +1039,7 @@ CHECK_REQS: foreach (@regs) {
$temp = get_reg_class($_);
if (!defined($temp)) {
print STDERR "Unknown register '$_'!\n";
return (undef, undef, undef, undef);
return (undef, undef, undef, undef, undef);
}
# set class
......@@ -1043,7 +1048,7 @@ CHECK_REQS: foreach (@regs) {
} elsif ($class ne $temp) {
# all registers must belong to the same class
print STDERR "Registerclass mismatch. '$_' is not member of class '$class'.\n";
return (undef, undef, undef, undef);
return (undef, undef, undef, undef, undef);
}
# calculate position inside the initializer bitfield (only 32 bits per
......@@ -1073,7 +1078,7 @@ CHECK_REQS: foreach (@regs) {
if(defined($limit_bitsets{$limit_name})) {
$limit_name = $limit_bitsets{$limit_name};
return ($class, $limit_name, $same_pos, $different_pos);
return ($class, $limit_name, $same_pos, $same_pos2, $different_pos);
}
$limit_bitsets{$limit_name} = $limit_name;
......@@ -1111,7 +1116,7 @@ CHECK_REQS: foreach (@regs) {
push(@obst_limit_func, " };\n");
}
return ($class, $limit_name, $same_pos, $different_pos);
return ($class, $limit_name, $same_pos, $same_pos2, $different_pos);
}
###
......@@ -1133,7 +1138,7 @@ sub generate_requirements {
arch_register_req_type_none,
NULL, /* regclass */
NULL, /* limit bitset */
-1, /* same pos */
{ -1, -1 }, /* same pos */
-1 /* different pos */
};
......@@ -1148,7 +1153,7 @@ EOF
arch_register_req_type_should_be_different_from_all,
& ${arch}_reg_classes[CLASS_${arch}_${class}],
NULL, /* limit bitset */
-1, /* same pos */
{ -1, -1 }, /* same pos */
-1 /* different pos */
};
......@@ -1160,7 +1165,7 @@ EOF
arch_register_req_type_normal,
& ${arch}_reg_classes[CLASS_${arch}_${class}],
NULL, /* limit bitset */
-1, /* same pos */
{ -1, -1 }, /* same pos */
-1 /* different pos */
};
......@@ -1168,7 +1173,7 @@ EOF
} else {
my @req_type_mask;
my ($regclass, $limit_bitset, $same_pos, $different_pos)
my ($regclass, $limit_bitset, $same_pos, $same_pos2, $different_pos)
= build_subset_class_func($node, $op, $idx, $is_in, $reqs);
if (!defined($regclass)) {
......@@ -1194,7 +1199,8 @@ EOF
if(!defined($limit_bitset)) {
$limit_bitset = "NULL";
}
my $same_pos_str = (defined($same_pos) ? $same_pos : "-1");
my $same_pos_str = (defined($same_pos) ? $same_pos : "-1");
my $same_pos_str2 = (defined($same_pos2) ? $same_pos2 : "-1");
my $different_pos_str = (defined($different_pos) ? $different_pos : "-1");
$class = $regclass;
......@@ -1203,7 +1209,7 @@ EOF
${reqtype},
& ${arch}_reg_classes[CLASS_${arch}_${class}],
${limit_bitset},
${same_pos_str}, /* same pos */
{ ${same_pos_str}, ${same_pos_str2} }, /* same pos */
${different_pos_str} /* different pos */
};
......
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