Allow two should-be-same constraints for every out register. This is useful for commu...
authorChristoph Mallon <christoph.mallon@gmx.de>
Thu, 27 Sep 2007 15:07:27 +0000 (15:07 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Thu, 27 Sep 2007 15:07:27 +0000 (15:07 +0000)
[r15953]

14 files changed:
ir/be/TEMPLATE/TEMPLATE_new_nodes.c
ir/be/arm/arm_new_nodes.c
ir/be/bearch.c
ir/be/bearch_t.h
ir/be/becopyopt.c
ir/be/benode.c
ir/be/beraextern.c
ir/be/ia32/ia32_finish.c
ir/be/ia32/ia32_new_nodes.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c
ir/be/mips/mips_new_nodes.c
ir/be/ppc32/ppc32_new_nodes.c
ir/be/scripts/generate_new_opcodes.pl

index 07051f3..b0bb78a 100644 (file)
@@ -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) {
index 8600877..41051fd 100644 (file)
@@ -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) {
index 30d02c1..01087c4 100644 (file)
@@ -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)) {
index d5133a3..3510418 100644 (file)
@@ -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). */
index 70ebdfc..26d0686 100644 (file)
@@ -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));
+                       }
                }
        }
 }
index ea3339c..7fc22c5 100644 (file)
@@ -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;
 }
index 6f66ad0..9caded9 100644 (file)
@@ -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));
+                               }
                        }
                }
        }
index 884024f..99f3202 100644 (file)
@@ -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);
index dbc495f..c067ac3 100644 (file)
@@ -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) {
index 1865057..03be763 100644 (file)
@@ -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,
index 249a370..5a1e37b 100644 (file)
@@ -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
index 029f6b2..c390794 100644 (file)
@@ -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) {
index 07a8b33..c223508 100644 (file)
@@ -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) {
index f06d083..a838609 100755 (executable)
@@ -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 */
 };