mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
c7d42abb94
commit
54f044ebbb
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
54
gcc/recog.c
54
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue