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:
parent
39abbb865c
commit
2f0b80c7a4
@ -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
|
||||
|
@ -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
|
||||
|
@ -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++]
|
||||
|
@ -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.
|
||||
|
52
gcc/testsuite/gcc.dg/pr87600-1.c
Normal file
52
gcc/testsuite/gcc.dg/pr87600-1.c
Normal 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;
|
||||
}
|
44
gcc/testsuite/gcc.dg/pr87600-2.c
Normal file
44
gcc/testsuite/gcc.dg/pr87600-2.c
Normal 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;
|
||||
}
|
19
gcc/testsuite/gcc.dg/pr87600.h
Normal file
19
gcc/testsuite/gcc.dg/pr87600.h
Normal 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
|
Loading…
Reference in New Issue
Block a user