diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/lra-constraints.c | 60 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr56148.c | 12 |
4 files changed, 65 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4308b5b..2e7171f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2013-02-12 Vladimir Makarov <vmakarov@redhat.com> + + PR inline-asm/56148 + * lra-constraints.c (process_alt_operands): Match early clobber + operand with itself. Check conflicts with earlyclobner only if + the operand is not reloaded. Prefer to reload conflicting operand + if earlyclobber and matching operands are the same. + 2013-02-12 Richard Biener <rguenther@suse.de> PR lto/56297 diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 49c9723..d3f4420 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -1533,8 +1533,8 @@ process_alt_operands (int only_alternative) if (! curr_static_id->operand[m].early_clobber || operand_reg[nop] == NULL_RTX || (find_regno_note (curr_insn, REG_DEAD, - REGNO (operand_reg[nop])) - != NULL_RTX)) + REGNO (op)) + || REGNO (op) == REGNO (operand_reg[m]))) match_p = true; } if (match_p) @@ -2059,6 +2059,7 @@ process_alt_operands (int only_alternative) if ((! curr_alt_win[i] && ! curr_alt_match_win[i]) || hard_regno[i] < 0) continue; + lra_assert (operand_reg[i] != NULL_RTX); clobbered_hard_regno = hard_regno[i]; CLEAR_HARD_REG_SET (temp_set); add_to_hard_reg_set (&temp_set, biggest_mode[i], clobbered_hard_regno); @@ -2073,30 +2074,49 @@ process_alt_operands (int only_alternative) else if ((curr_alt_matches[j] == i && curr_alt_match_win[j]) || (curr_alt_matches[i] == j && curr_alt_match_win[i])) continue; - else if (uses_hard_regs_p (*curr_id->operand_loc[j], temp_set)) + /* If we don't reload j-th operand, check conflicts. */ + else if ((curr_alt_win[j] || curr_alt_match_win[j]) + && uses_hard_regs_p (*curr_id->operand_loc[j], temp_set)) break; if (j >= n_operands) continue; - /* We need to reload early clobbered register. */ - for (j = 0; j < n_operands; j++) - if (curr_alt_matches[j] == i) - { - curr_alt_match_win[j] = false; - losers++; - overall += LRA_LOSER_COST_FACTOR; - } - if (! curr_alt_match_win[i]) - curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = i; + /* If earlyclobber operand conflicts with another + non-matching operand which is actually the same register + as the earlyclobber operand, it is better to reload the + another operand as an operand matching the earlyclobber + operand can be also the same. */ + if (operand_reg[j] != NULL_RTX && ! curr_alt_match_win[j] + && REGNO (operand_reg[i]) == REGNO (operand_reg[j])) + { + curr_alt_win[j] = false; + curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = j; + losers++; + overall += LRA_LOSER_COST_FACTOR; + } else { - /* Remember pseudos used for match reloads are never - inherited. */ - lra_assert (curr_alt_matches[i] >= 0); - curr_alt_win[curr_alt_matches[i]] = false; + /* We need to reload early clobbered register and the + matched registers. */ + for (j = 0; j < n_operands; j++) + if (curr_alt_matches[j] == i) + { + curr_alt_match_win[j] = false; + losers++; + overall += LRA_LOSER_COST_FACTOR; + } + if (! curr_alt_match_win[i]) + curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = i; + else + { + /* Remember pseudos used for match reloads are never + inherited. */ + lra_assert (curr_alt_matches[i] >= 0); + curr_alt_win[curr_alt_matches[i]] = false; + } + curr_alt_win[i] = curr_alt_match_win[i] = false; + losers++; + overall += LRA_LOSER_COST_FACTOR; } - curr_alt_win[i] = curr_alt_match_win[i] = false; - losers++; - overall += LRA_LOSER_COST_FACTOR; } small_class_operands_num = 0; for (nop = 0; nop < n_operands; nop++) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ab009a5..7d07c20 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-02-12 Vladimir Makarov <vmakarov@redhat.com> + + PR inline-asm/56148 + * gcc.target/i386/pr56148.c: New test. + 2013-02-12 Dominique d'Humieres <dominiq@lps.ens.fr> Tobias Burnus <burnus@net-b.de> diff --git a/gcc/testsuite/gcc.target/i386/pr56148.c b/gcc/testsuite/gcc.target/i386/pr56148.c new file mode 100644 index 0000000..78d2efb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr56148.c @@ -0,0 +1,12 @@ +/* PR inline-asm/56148 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void +foo (void) +{ + unsigned char e[16]; + unsigned long a, b, c, d; + __asm__ __volatile__ ("" : "=d" (a), "=&c" (c), "=&D" (d), "=&a" (b) + : "0" (-1U), "mr" (e), "1" (128 >> 5), "2" (e), "3" (-1U)); +} |