+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
* 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
&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
}
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
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++]
+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.
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+#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