}
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) {
}
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) {
}
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)) {
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). */
/* 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));
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));
+ }
}
}
}
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;
}
/* 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));
+ }
}
}
}
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);
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);
}
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) {
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",
},
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",
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",
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',
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',
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',
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,
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,
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,
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,
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,
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" ],
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,
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
}
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) {
}
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) {
my $has_limit = 0;
my $limit_name;
my $same_pos = undef;
+ my $same_pos2 = undef;
my $different_pos = undef;
my $temp;
my @obst_init;
# 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
# 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)) {
# 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;
$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
} 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
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;
push(@obst_limit_func, " };\n");
}
- return ($class, $limit_name, $same_pos, $different_pos);
+ return ($class, $limit_name, $same_pos, $same_pos2, $different_pos);
}
###
arch_register_req_type_none,
NULL, /* regclass */
NULL, /* limit bitset */
- -1, /* same pos */
+ { -1, -1 }, /* same pos */
-1 /* different pos */
};
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 */
};
arch_register_req_type_normal,
& ${arch}_reg_classes[CLASS_${arch}_${class}],
NULL, /* limit bitset */
- -1, /* same pos */
+ { -1, -1 }, /* same pos */
-1 /* different pos */
};
} 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)) {
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;
${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 */
};