aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Bergner <bergner@linux.ibm.com>2018-11-08 22:39:45 +0000
committerPeter Bergner <bergner@gcc.gnu.org>2018-11-08 16:39:45 -0600
commit2f0b80c7a4ab4254f57ba63de26ebb7896e3742d (patch)
tree0b641c23205b2def0563667593bc61bb7bc6e042
parent39abbb865c2363ab508bdf5dc24553e448c803b0 (diff)
downloadgcc-2f0b80c7a4ab4254f57ba63de26ebb7896e3742d.zip
gcc-2f0b80c7a4ab4254f57ba63de26ebb7896e3742d.tar.gz
gcc-2f0b80c7a4ab4254f57ba63de26ebb7896e3742d.tar.bz2
re PR rtl-optimization/87600 (Fix for PRs 86939 and 87479 causes build issues for several targets)
gcc/ PR rtl-optimization/87600 * cfgexpand.c (expand_asm_stmt): Catch illegal asm constraint usage. * lra-constraints.c (process_alt_operands): Skip illegal hard register usage. Prefer reloading non hard register operands. gcc/testsuite/ PR rtl-optimization/87600 * gcc.dg/pr87600.h: New file. * gcc.dg/pr87600-1.c: New test. * gcc.dg/pr87600-2.c: Likewise. From-SVN: r265942
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/cfgexpand.c49
-rw-r--r--gcc/lra-constraints.c60
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/pr87600-1.c52
-rw-r--r--gcc/testsuite/gcc.dg/pr87600-2.c44
-rw-r--r--gcc/testsuite/gcc.dg/pr87600.h19
7 files changed, 233 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a7a6ddb..8578874 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2018-11-08 Peter Bergner <bergner@linux.ibm.com>
+
+ PR rtl-optimization/87600
+ * cfgexpand.c (expand_asm_stmt): Catch illegal asm constraint usage.
+ * lra-constraints.c (process_alt_operands): Skip illegal hard
+ register usage. Prefer reloading non hard register operands.
+
+gcc/testsuite/
+ PR rtl-optimization/87600
+ * gcc.dg/pr87600.h: New file.
+ * gcc.dg/pr87600-1.c: New test.
+ * gcc.dg/pr87600-2.c: Likewise.
+
2018-11-08 Sandra Loosemore <sandra@codesourcery.com>
PR other/36572
@@ -12,7 +25,7 @@
* common.opt (-fuse-ld=lld): New option.
* doc/invoke.texi (-fuse-ld=lld): Document.
* opts.c (common_handle_option): Handle OPT_fuse_ld_lld.
-
+
2018-11-08 Paul Koning <ni1d@arrl.net>
* config/pdp11/constraints.md: Add "Z" series constraints for use
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 672fc57..8fa392f 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3010,6 +3010,55 @@ expand_asm_stmt (gasm *stmt)
&allows_mem, &allows_reg, &is_inout))
return;
+ /* If the output is a hard register, verify it doesn't conflict with
+ any other operand's possible hard register use. */
+ if (DECL_P (val)
+ && REG_P (DECL_RTL (val))
+ && HARD_REGISTER_P (DECL_RTL (val)))
+ {
+ unsigned j, output_hregno = REGNO (DECL_RTL (val));
+ bool early_clobber_p = strchr (constraints[i], '&') != NULL;
+ unsigned long match;
+
+ /* Verify the other outputs do not use the same hard register. */
+ for (j = i + 1; j < noutputs; ++j)
+ if (DECL_P (output_tvec[j])
+ && REG_P (DECL_RTL (output_tvec[j]))
+ && HARD_REGISTER_P (DECL_RTL (output_tvec[j]))
+ && output_hregno == REGNO (DECL_RTL (output_tvec[j])))
+ error ("invalid hard register usage between output operands");
+
+ /* Verify matching constraint operands use the same hard register
+ and that the non-matching constraint operands do not use the same
+ hard register if the output is an early clobber operand. */
+ for (j = 0; j < ninputs; ++j)
+ if (DECL_P (input_tvec[j])
+ && REG_P (DECL_RTL (input_tvec[j]))
+ && HARD_REGISTER_P (DECL_RTL (input_tvec[j])))
+ {
+ unsigned input_hregno = REGNO (DECL_RTL (input_tvec[j]));
+ switch (*constraints[j + noutputs])
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ match = strtoul (constraints[j + noutputs], NULL, 10);
+ break;
+ default:
+ match = ULONG_MAX;
+ break;
+ }
+ if (i == match
+ && output_hregno != input_hregno)
+ error ("invalid hard register usage between output operand "
+ "and matching constraint operand");
+ else if (early_clobber_p
+ && i != match
+ && output_hregno == input_hregno)
+ error ("invalid hard register usage between earlyclobber "
+ "operand and input operand");
+ }
+ }
+
if (! allows_reg
&& (allows_mem
|| is_inout
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index ab61989..88546d2 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -2146,9 +2146,32 @@ process_alt_operands (int only_alternative)
}
else
{
- /* Operands don't match. Both operands must
- allow a reload register, otherwise we
- cannot make them match. */
+ /* Operands don't match. If the operands are
+ different user defined explicit hard registers,
+ then we cannot make them match. */
+ if ((REG_P (*curr_id->operand_loc[nop])
+ || SUBREG_P (*curr_id->operand_loc[nop]))
+ && (REG_P (*curr_id->operand_loc[m])
+ || SUBREG_P (*curr_id->operand_loc[m])))
+ {
+ rtx nop_reg = *curr_id->operand_loc[nop];
+ if (SUBREG_P (nop_reg))
+ nop_reg = SUBREG_REG (nop_reg);
+ rtx m_reg = *curr_id->operand_loc[m];
+ if (SUBREG_P (m_reg))
+ m_reg = SUBREG_REG (m_reg);
+
+ if (REG_P (nop_reg)
+ && HARD_REGISTER_P (nop_reg)
+ && REG_USERVAR_P (nop_reg)
+ && REG_P (m_reg)
+ && HARD_REGISTER_P (m_reg)
+ && REG_USERVAR_P (m_reg))
+ break;
+ }
+
+ /* Both operands must allow a reload register,
+ otherwise we cannot make them match. */
if (curr_alt[m] == NO_REGS)
break;
/* Retroactively mark the operand we had to
@@ -2910,18 +2933,31 @@ process_alt_operands (int only_alternative)
if (first_conflict_j < 0)
first_conflict_j = j;
last_conflict_j = j;
+ /* Both the earlyclobber operand and conflicting operand
+ cannot both be user defined hard registers. */
+ if (HARD_REGISTER_P (operand_reg[i])
+ && REG_USERVAR_P (operand_reg[i])
+ && operand_reg[j] != NULL_RTX
+ && HARD_REGISTER_P (operand_reg[j])
+ && REG_USERVAR_P (operand_reg[j]))
+ fatal_insn ("unable to generate reloads for "
+ "impossible constraints:", curr_insn);
}
if (last_conflict_j < 0)
continue;
- /* 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 (first_conflict_j == last_conflict_j
- && operand_reg[last_conflict_j] != NULL_RTX
- && ! curr_alt_match_win[last_conflict_j]
- && REGNO (operand_reg[i]) == REGNO (operand_reg[last_conflict_j]))
+
+ /* If an earlyclobber operand conflicts with another non-matching
+ operand (ie, they have been assigned the same hard register),
+ then it is better to reload the other operand, as there may
+ exist yet another operand with a matching constraint associated
+ with the earlyclobber operand. However, if one of the operands
+ is an explicit use of a hard register, then we must reload the
+ other non-hard register operand. */
+ if (HARD_REGISTER_P (operand_reg[i])
+ || (first_conflict_j == last_conflict_j
+ && operand_reg[last_conflict_j] != NULL_RTX
+ && !curr_alt_match_win[last_conflict_j]
+ && !HARD_REGISTER_P (operand_reg[last_conflict_j])))
{
curr_alt_win[last_conflict_j] = false;
curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++]
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c227dc9..4769e45 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2018-11-08 Peter Bergner <bergner@linux.ibm.com>
+
+ PR rtl-optimization/87600
+ * gcc.dg/pr87600.h: New file.
+ * gcc.dg/pr87600-1.c: New test.
+ * gcc.dg/pr87600-2.c: Likewise.
+
2018-11-08 Jakub Jelinek <jakub@redhat.com>
* c-c++-common/gomp/atomic-17.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr87600-1.c b/gcc/testsuite/gcc.dg/pr87600-1.c
new file mode 100644
index 0000000..3517957
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87600-1.c
@@ -0,0 +1,52 @@
+/* PR rtl-optimization/87600 */
+/* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* s390*-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+
+#include "pr87600.h"
+
+/* The following are all valid uses of local register variables. */
+
+long
+test0 (long arg)
+{
+ register long var asm (REG1);
+ asm ("blah %0 %1" : "+&r" (var) : "r" (arg));
+ return var;
+}
+
+long
+test1 (long arg0, long arg1)
+{
+ register long var asm (REG1);
+ asm ("blah %0, %1, %2" : "=&r" (var) : "r" (arg0), "0" (arg1));
+ return var + arg1;
+}
+
+long
+test2 (void)
+{
+ register long var1 asm (REG1);
+ register long var2 asm (REG1);
+ asm ("blah %0 %1" : "=&r" (var1) : "0" (var2));
+ return var1;
+}
+
+long
+test3 (void)
+{
+ register long var1 asm (REG1);
+ register long var2 asm (REG2);
+ long var3;
+ asm ("blah %0 %1" : "=&r" (var1), "=r" (var3) : "1" (var2));
+ return var1 + var3;
+}
+
+long
+test4 (void)
+{
+ register long var1 asm (REG1);
+ register long var2 asm (REG2);
+ register long var3 asm (REG2);
+ asm ("blah %0 %1" : "=&r" (var1), "=r" (var2) : "1" (var3));
+ return var1;
+}
diff --git a/gcc/testsuite/gcc.dg/pr87600-2.c b/gcc/testsuite/gcc.dg/pr87600-2.c
new file mode 100644
index 0000000..e8a9f19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87600-2.c
@@ -0,0 +1,44 @@
+/* PR rtl-optimization/87600 */
+/* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* s390*-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+
+#include "pr87600.h"
+
+/* The following are all invalid uses of local register variables. */
+
+long
+test0 (void)
+{
+ register long var1 asm (REG1);
+ register long var2 asm (REG1);
+ asm ("blah %0 %1" : "=r" (var1), "=r" (var2)); /* { dg-error "invalid hard register usage between output operands" } */
+ return var1;
+}
+
+long
+test1 (void)
+{
+ register long var1 asm (REG1);
+ register long var2 asm (REG2);
+ asm ("blah %0 %1" : "=r" (var1) : "0" (var2)); /* { dg-error "invalid hard register usage between output operand and matching constraint operand" } */
+ return var1;
+}
+
+long
+test2 (void)
+{
+ register long var1 asm (REG1);
+ register long var2 asm (REG1);
+ asm ("blah %0 %1" : "=&r" (var1) : "r" (var2)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+ return var1;
+}
+
+long
+test3 (void)
+{
+ register long var1 asm (REG1);
+ register long var2 asm (REG1);
+ long var3;
+ asm ("blah %0 %1" : "=&r" (var1), "=r" (var3) : "1" (var2)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+ return var1 + var3;
+}
diff --git a/gcc/testsuite/gcc.dg/pr87600.h b/gcc/testsuite/gcc.dg/pr87600.h
new file mode 100644
index 0000000..5ebb928
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87600.h
@@ -0,0 +1,19 @@
+#if defined (__aarch64__)
+# define REG1 "x0"
+# define REG2 "x1"
+#elif defined (__arm__)
+# define REG1 "r0"
+# define REG2 "r1"
+#elif defined (__i386__)
+# define REG1 "%eax"
+# define REG2 "%edx"
+#elif defined (__powerpc__)
+# define REG1 "r3"
+# define REG2 "r4"
+#elif defined (__s390__)
+# define REG1 "0"
+# define REG2 "1"
+#elif defined (__x86_64__)
+# define REG1 "rax"
+# define REG2 "rdx"
+#endif