summaryrefslogtreecommitdiff
path: root/gcc/cfgexpand.c
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 /gcc/cfgexpand.c
parent39abbb865c2363ab508bdf5dc24553e448c803b0 (diff)
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
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r--gcc/cfgexpand.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 672fc57687c..8fa392fcd8a 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