aboutsummaryrefslogtreecommitdiff
path: root/gcc/recog.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2010-06-24 19:48:16 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2010-06-24 19:48:16 +0200
commit54f044ebbbdce8a6758b3fa7bdbd854632bc47b3 (patch)
tree342f106af8349c0f121d3e089e983f9d4013abf1 /gcc/recog.c
parentc7d42abb94d423e65a2cbc7334b7ca81c3ff6f5f (diff)
downloadgcc-54f044ebbbdce8a6758b3fa7bdbd854632bc47b3.zip
gcc-54f044ebbbdce8a6758b3fa7bdbd854632bc47b3.tar.gz
gcc-54f044ebbbdce8a6758b3fa7bdbd854632bc47b3.tar.bz2
re PR middle-end/44492 (auto-inc-dec pushes PRE_MODIFY/PRE_INC into inline asm operands)
PR middle-end/44492 * recog.h (struct recog_data): Add is_asm field. * recog.c (asm_operand_ok, constrain_operands): If neither < nor > is present in constraints of inline-asm operand and memory operand contains {PRE,POST}_{INC,DEC,MODIFY}, return 0. (extract_insn): Initialize recog_data.is_asm. * doc/md.texi (Constraints): Document operand side-effect rules. * g++.dg/torture/pr44492.C: New test. From-SVN: r161328
Diffstat (limited to 'gcc/recog.c')
-rw-r--r--gcc/recog.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/gcc/recog.c b/gcc/recog.c
index 1847c23..43f901f 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1601,6 +1601,9 @@ int
asm_operand_ok (rtx op, const char *constraint, const char **constraints)
{
int result = 0;
+#ifdef AUTO_INC_DEC
+ bool incdec_ok = false;
+#endif
/* Use constrain_operands after reload. */
gcc_assert (!reload_completed);
@@ -1608,7 +1611,7 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
/* Empty constraint string is the same as "X,...,X", i.e. X for as
many alternatives as required to match the other operands. */
if (*constraint == '\0')
- return 1;
+ result = 1;
while (*constraint)
{
@@ -1685,6 +1688,9 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
result = 1;
+#ifdef AUTO_INC_DEC
+ incdec_ok = true;
+#endif
break;
case '>':
@@ -1693,6 +1699,9 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
|| GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
result = 1;
+#ifdef AUTO_INC_DEC
+ incdec_ok = true;
+#endif
break;
case 'E':
@@ -1814,6 +1823,23 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
return 0;
}
+#ifdef AUTO_INC_DEC
+ /* For operands without < or > constraints reject side-effects. */
+ if (!incdec_ok && result && MEM_P (op))
+ switch (GET_CODE (XEXP (op, 0)))
+ {
+ case PRE_INC:
+ case POST_INC:
+ case PRE_DEC:
+ case POST_DEC:
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ return 0;
+ default:
+ break;
+ }
+#endif
+
return result;
}
@@ -2039,6 +2065,7 @@ extract_insn (rtx insn)
recog_data.n_operands = 0;
recog_data.n_alternatives = 0;
recog_data.n_dups = 0;
+ recog_data.is_asm = false;
switch (GET_CODE (body))
{
@@ -2085,6 +2112,7 @@ extract_insn (rtx insn)
while (*p)
recog_data.n_alternatives += (*p++ == ',');
}
+ recog_data.is_asm = true;
break;
}
fatal_insn_not_found (insn);
@@ -2699,6 +2727,30 @@ constrain_operands (int strict)
= recog_data.operand[funny_match[funny_match_index].this_op];
}
+#ifdef AUTO_INC_DEC
+ /* For operands without < or > constraints reject side-effects. */
+ if (recog_data.is_asm)
+ {
+ for (opno = 0; opno < recog_data.n_operands; opno++)
+ if (MEM_P (recog_data.operand[opno]))
+ switch (GET_CODE (XEXP (recog_data.operand[opno], 0)))
+ {
+ case PRE_INC:
+ case POST_INC:
+ case PRE_DEC:
+ case POST_DEC:
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ if (strchr (recog_data.constraints[opno], '<') == NULL
+ || strchr (recog_data.constraints[opno], '>')
+ == NULL)
+ return 0;
+ break;
+ default:
+ break;
+ }
+ }
+#endif
return 1;
}
}