gcc/gcc44-pr44492.patch

208 lines
6.0 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

2010-06-24 Jakub Jelinek <jakub@redhat.com>
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.
--- gcc/doc/md.texi (revision 161327)
+++ gcc/doc/md.texi (revision 161328)
@@ -1052,6 +1052,10 @@ an operand may be in a register, and whi
operand can be a memory reference, and which kinds of address; whether the
operand may be an immediate constant, and which possible values it may
have. Constraints can also require two operands to match.
+Side-effects aren't allowed in operands of inline @code{asm}, unless
+@samp{<} or @samp{>} constraints are used, because there is no guarantee
+that the side-effects will happen exactly once in an instruction that can update
+the addressing register.
@ifset INTERNALS
@menu
@@ -1129,12 +1133,21 @@ would fit the @samp{m} constraint but no
@cindex @samp{<} in constraint
@item @samp{<}
A memory operand with autodecrement addressing (either predecrement or
-postdecrement) is allowed.
+postdecrement) is allowed. In inline @code{asm} this constraint is only
+allowed if the operand is used exactly once in an instruction that can
+handle the side-effects. Not using an operand with @samp{<} in constraint
+string in the inline @code{asm} pattern at all or using it in multiple
+instructions isn't valid, because the side-effects wouldn't be performed
+or would be performed more than once. Furthermore, on some targets
+the operand with @samp{<} in constraint string must be accompanied by
+special instruction suffixes like @code{%U0} instruction suffix on PowerPC
+or @code{%P0} on IA-64.
@cindex @samp{>} in constraint
@item @samp{>}
A memory operand with autoincrement addressing (either preincrement or
-postincrement) is allowed.
+postincrement) is allowed. In inline @code{asm} the same restrictions
+as for @samp{<} apply.
@cindex @samp{r} in constraint
@cindex registers in constraints
--- gcc/recog.c (revision 161327)
+++ gcc/recog.c (revision 161328)
@@ -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 *cons
/* 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 *cons
|| 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 *cons
|| 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 *cons
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;
}
}
--- gcc/recog.h (revision 161327)
+++ gcc/recog.h (revision 161328)
@@ -230,6 +230,9 @@ struct recog_data
/* The number of alternatives in the constraints for the insn. */
char n_alternatives;
+ /* True if insn is ASM_OPERANDS. */
+ bool is_asm;
+
/* Specifies whether an insn alternative is enabled using the
`enabled' attribute in the insn pattern definition. For back
ends not using the `enabled' attribute the array fields are
--- gcc/testsuite/g++.dg/torture/pr44492.C (revision 0)
+++ gcc/testsuite/g++.dg/torture/pr44492.C (revision 161328)
@@ -0,0 +1,31 @@
+// PR middle-end/44492
+// { dg-do run }
+
+struct T { unsigned long p; };
+struct S { T a, b, c; unsigned d; };
+
+__attribute__((noinline))
+void
+bar (const T &x, const T &y)
+{
+ if (x.p != 0x2348 || y.p != 0x2346)
+ __builtin_abort ();
+}
+
+__attribute__((noinline))
+void
+foo (S &s, T e)
+{
+ unsigned long a = e.p;
+ unsigned long b = s.b.p;
+ __asm__ volatile ("" : : "rm" (a), "rm" (b));
+ bar (e, s.b);
+}
+
+int
+main ()
+{
+ S s = { { 0x2345 }, { 0x2346 }, { 0x2347 }, 6 };
+ T t = { 0x2348 };
+ foo (s, t);
+}