aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/lra-constraints.c60
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr56148.c12
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));
+}