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
This commit is contained in:
Peter Bergner 2018-11-08 22:39:45 +00:00 committed by Peter Bergner
parent 39abbb865c
commit 2f0b80c7a4
7 changed files with 233 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -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++]

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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