diff options
author | Jakub Jelinek <jakub@redhat.com> | 2010-06-24 19:48:16 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2010-06-24 19:48:16 +0200 |
commit | 54f044ebbbdce8a6758b3fa7bdbd854632bc47b3 (patch) | |
tree | 342f106af8349c0f121d3e089e983f9d4013abf1 | |
parent | c7d42abb94d423e65a2cbc7334b7ca81c3ff6f5f (diff) | |
download | gcc-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
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/doc/md.texi | 17 | ||||
-rw-r--r-- | gcc/recog.c | 54 | ||||
-rw-r--r-- | gcc/recog.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr44492.C | 31 |
6 files changed, 117 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cb16414..b6e3eed 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +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. + 2010-06-24 Andi Kleen <ak@linux.intel.com> * c-parser.c (c_parser_conditional_expression): diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index c37bb03..46bd4f6 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -1052,6 +1052,10 @@ an operand may be in a register, and which kinds of register; whether the 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 not the @samp{o} constraint. @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 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; } } diff --git a/gcc/recog.h b/gcc/recog.h index c2972ab..71dba91f 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 351dcd8..ef242f6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-06-24 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/44492 + * g++.dg/torture/pr44492.C: New test. + 2010-06-24 Andi Kleen <ak@linux.intel.com> * c-c++-common/warn-omitted-condop.c: New. diff --git a/gcc/testsuite/g++.dg/torture/pr44492.C b/gcc/testsuite/g++.dg/torture/pr44492.C new file mode 100644 index 0000000..41669241 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr44492.C @@ -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); +} |