diff options
author | Peter Bergner <bergner@linux.ibm.com> | 2018-11-08 22:39:45 +0000 |
---|---|---|
committer | Peter Bergner <bergner@gcc.gnu.org> | 2018-11-08 16:39:45 -0600 |
commit | 2f0b80c7a4ab4254f57ba63de26ebb7896e3742d (patch) | |
tree | 0b641c23205b2def0563667593bc61bb7bc6e042 /gcc/cfgexpand.c | |
parent | 39abbb865c2363ab508bdf5dc24553e448c803b0 (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.c | 49 |
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 |