re PR c/24414 (Old-style asms don't clobber memory)

gcc/
2016-06-06  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR c/24414
        * cfgexpand.c (expand_asm_loc): Remove handling for ADDR_EXPR.
        Implicitly clobber memory for basic asm with non-empty assembler
        string.  Use targetm.md_asm_adjust also here.
        * compare-elim.c (arithmetic_flags_clobber_p): Use asm_noperands here.
        * final.c (final_scan_insn): Handle basic asm in PARALLEL block.
        * gimple.c (gimple_asm_clobbers_memory_p): Handle basic asm with
        non-empty assembler string.
        * ira.c (compute_regs_asm_clobbered): Use asm_noperands here.
        * recog.c (asm_noperands): Handle basic asm in PARALLEL block.
        (decode_asm_operands): Handle basic asm in PARALLEL block.
        (extract_insn): Handle basic asm in PARALLEL block.
        * doc/extend.texi: Mention new behavior of basic asm.
        * config/ia64/ia64 (rtx_needs_barrier): Handle ASM_INPUT here.
        * config/pa/pa.c (branch_to_delay_slot_p, branch_needs_nop_p,
        branch_needs_nop_p): Use asm_noperands.

gcc/testsuite/
2016-06-06  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR c/24414
        * gcc.target/i386/pr24414.c: New test.

From-SVN: r237133
This commit is contained in:
Bernd Edlinger 2016-06-06 12:31:59 +00:00 committed by Bernd Edlinger
parent 690f24b775
commit 93671519e2
12 changed files with 111 additions and 14 deletions

View File

@ -1,3 +1,22 @@
2016-06-06 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR c/24414
* cfgexpand.c (expand_asm_loc): Remove handling for ADDR_EXPR.
Implicitly clobber memory for basic asm with non-empty assembler
string. Use targetm.md_asm_adjust also here.
* compare-elim.c (arithmetic_flags_clobber_p): Use asm_noperands here.
* final.c (final_scan_insn): Handle basic asm in PARALLEL block.
* gimple.c (gimple_asm_clobbers_memory_p): Handle basic asm with
non-empty assembler string.
* ira.c (compute_regs_asm_clobbered): Use asm_noperands here.
* recog.c (asm_noperands): Handle basic asm in PARALLEL block.
(decode_asm_operands): Handle basic asm in PARALLEL block.
(extract_insn): Handle basic asm in PARALLEL block.
* doc/extend.texi: Mention new behavior of basic asm.
* config/ia64/ia64 (rtx_needs_barrier): Handle ASM_INPUT here.
* config/pa/pa.c (branch_to_delay_slot_p, branch_needs_nop_p,
branch_needs_nop_p): Use asm_noperands.
2016-06-06 Jose E. Marchesi <jose.marchesi@oracle.com> 2016-06-06 Jose E. Marchesi <jose.marchesi@oracle.com>
* config/sparc/sparc.md (cpu): Add niagara7 cpu type. * config/sparc/sparc.md (cpu): Add niagara7 cpu type.

View File

@ -2674,15 +2674,40 @@ expand_asm_loc (tree string, int vol, location_t locus)
{ {
rtx body; rtx body;
if (TREE_CODE (string) == ADDR_EXPR)
string = TREE_OPERAND (string, 0);
body = gen_rtx_ASM_INPUT_loc (VOIDmode, body = gen_rtx_ASM_INPUT_loc (VOIDmode,
ggc_strdup (TREE_STRING_POINTER (string)), ggc_strdup (TREE_STRING_POINTER (string)),
locus); locus);
MEM_VOLATILE_P (body) = vol; MEM_VOLATILE_P (body) = vol;
/* Non-empty basic ASM implicitly clobbers memory. */
if (TREE_STRING_LENGTH (string) != 0)
{
rtx asm_op, clob;
unsigned i, nclobbers;
auto_vec<rtx> input_rvec, output_rvec;
auto_vec<const char *> constraints;
auto_vec<rtx> clobber_rvec;
HARD_REG_SET clobbered_regs;
CLEAR_HARD_REG_SET (clobbered_regs);
clob = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode));
clobber_rvec.safe_push (clob);
if (targetm.md_asm_adjust)
targetm.md_asm_adjust (output_rvec, input_rvec,
constraints, clobber_rvec,
clobbered_regs);
asm_op = body;
nclobbers = clobber_rvec.length ();
body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (1 + nclobbers));
XVECEXP (body, 0, 0) = asm_op;
for (i = 0; i < nclobbers; i++)
XVECEXP (body, 0, i + 1) = gen_rtx_CLOBBER (VOIDmode, clobber_rvec[i]);
}
emit_insn (body); emit_insn (body);
} }

View File

@ -162,7 +162,7 @@ arithmetic_flags_clobber_p (rtx_insn *insn)
if (!NONJUMP_INSN_P (insn)) if (!NONJUMP_INSN_P (insn))
return false; return false;
pat = PATTERN (insn); pat = PATTERN (insn);
if (extract_asm_operands (pat)) if (asm_noperands (pat) >= 0)
return false; return false;
if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) == 2) if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) == 2)

View File

@ -6558,6 +6558,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
case USE: case USE:
case CALL: case CALL:
case ASM_OPERANDS: case ASM_OPERANDS:
case ASM_INPUT:
need_barrier |= rtx_needs_barrier (pat, flags, pred); need_barrier |= rtx_needs_barrier (pat, flags, pred);
break; break;

View File

@ -6442,7 +6442,7 @@ branch_to_delay_slot_p (rtx_insn *insn)
the branch is followed by an asm. */ the branch is followed by an asm. */
if (!insn if (!insn
|| GET_CODE (PATTERN (insn)) == ASM_INPUT || GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX || asm_noperands (PATTERN (insn)) >= 0
|| get_attr_length (insn) > 0) || get_attr_length (insn) > 0)
break; break;
} }
@ -6473,7 +6473,7 @@ branch_needs_nop_p (rtx_insn *insn)
return TRUE; return TRUE;
if (!(GET_CODE (PATTERN (insn)) == ASM_INPUT if (!(GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX) || asm_noperands (PATTERN (insn)) >= 0)
&& get_attr_length (insn) > 0) && get_attr_length (insn) > 0)
break; break;
} }
@ -6497,7 +6497,7 @@ use_skip_p (rtx_insn *insn)
/* We can't rely on the length of asms, so we can't skip asms. */ /* We can't rely on the length of asms, so we can't skip asms. */
if (!insn if (!insn
|| GET_CODE (PATTERN (insn)) == ASM_INPUT || GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX) || asm_noperands (PATTERN (insn)) >= 0)
break; break;
if (get_attr_length (insn) == 4 if (get_attr_length (insn) == 4
&& jump_insn == next_active_insn (insn)) && jump_insn == next_active_insn (insn))

View File

@ -7581,7 +7581,7 @@ means there is no way to communicate to the compiler what is happening
inside them. GCC has no visibility of symbols in the @code{asm} and may inside them. GCC has no visibility of symbols in the @code{asm} and may
discard them as unreferenced. It also does not know about side effects of discard them as unreferenced. It also does not know about side effects of
the assembler code, such as modifications to memory or registers. Unlike the assembler code, such as modifications to memory or registers. Unlike
some compilers, GCC assumes that no changes to either memory or registers some compilers, GCC assumes that no changes to general purpose registers
occur. This assumption may change in a future release. occur. This assumption may change in a future release.
To avoid complications from future changes to the semantics and the To avoid complications from future changes to the semantics and the
@ -7605,6 +7605,10 @@ all basic @code{asm} blocks use the assembler dialect specified by the
Basic @code{asm} provides no Basic @code{asm} provides no
mechanism to provide different assembler strings for different dialects. mechanism to provide different assembler strings for different dialects.
For basic @code{asm} with non-empty assembler string GCC assumes
the assembler block does not change any general purpose registers,
but it may read or write any globally accessible variable.
Here is an example of basic @code{asm} for i386: Here is an example of basic @code{asm} for i386:
@example @example

View File

@ -2566,6 +2566,10 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
(*debug_hooks->source_line) (last_linenum, last_filename, (*debug_hooks->source_line) (last_linenum, last_filename,
last_discriminator, is_stmt); last_discriminator, is_stmt);
if (GET_CODE (body) == PARALLEL
&& GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
body = XVECEXP (body, 0, 0);
if (GET_CODE (body) == ASM_INPUT) if (GET_CODE (body) == ASM_INPUT)
{ {
const char *string = XSTR (body, 0); const char *string = XSTR (body, 0);

View File

@ -2583,6 +2583,10 @@ gimple_asm_clobbers_memory_p (const gasm *stmt)
return true; return true;
} }
/* Non-empty basic ASM implicitly clobbers memory. */
if (gimple_asm_input_p (stmt) && strlen (gimple_asm_string (stmt)) != 0)
return true;
return false; return false;
} }

View File

@ -2233,7 +2233,7 @@ compute_regs_asm_clobbered (void)
{ {
df_ref def; df_ref def;
if (NONDEBUG_INSN_P (insn) && extract_asm_operands (PATTERN (insn))) if (NONDEBUG_INSN_P (insn) && asm_noperands (PATTERN (insn)) >= 0)
FOR_EACH_INSN_DEF (def, insn) FOR_EACH_INSN_DEF (def, insn)
{ {
unsigned int dregno = DF_REF_REGNO (def); unsigned int dregno = DF_REF_REGNO (def);

View File

@ -1470,22 +1470,34 @@ extract_asm_operands (rtx body)
/* If BODY is an insn body that uses ASM_OPERANDS, /* If BODY is an insn body that uses ASM_OPERANDS,
return the number of operands (both input and output) in the insn. return the number of operands (both input and output) in the insn.
If BODY is an insn body that uses ASM_INPUT with CLOBBERS in PARALLEL,
return 0.
Otherwise return -1. */ Otherwise return -1. */
int int
asm_noperands (const_rtx body) asm_noperands (const_rtx body)
{ {
rtx asm_op = extract_asm_operands (CONST_CAST_RTX (body)); rtx asm_op = extract_asm_operands (CONST_CAST_RTX (body));
int n_sets = 0; int i, n_sets = 0;
if (asm_op == NULL) if (asm_op == NULL)
return -1; {
if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) >= 2
&& GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
{
/* body is [(asm_input ...) (clobber (reg ...))...]. */
for (i = XVECLEN (body, 0) - 1; i > 0; i--)
if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
return -1;
return 0;
}
return -1;
}
if (GET_CODE (body) == SET) if (GET_CODE (body) == SET)
n_sets = 1; n_sets = 1;
else if (GET_CODE (body) == PARALLEL) else if (GET_CODE (body) == PARALLEL)
{ {
int i;
if (GET_CODE (XVECEXP (body, 0, 0)) == SET) if (GET_CODE (XVECEXP (body, 0, 0)) == SET)
{ {
/* Multiple output operands, or 1 output plus some clobbers: /* Multiple output operands, or 1 output plus some clobbers:
@ -1540,9 +1552,12 @@ asm_noperands (const_rtx body)
the locations of the operands within the insn into the vector OPERAND_LOCS, the locations of the operands within the insn into the vector OPERAND_LOCS,
and the constraints for the operands into CONSTRAINTS. and the constraints for the operands into CONSTRAINTS.
Write the modes of the operands into MODES. Write the modes of the operands into MODES.
Write the location info into LOC.
Return the assembler-template. Return the assembler-template.
If BODY is an insn body that uses ASM_INPUT with CLOBBERS in PARALLEL,
return the basic assembly string.
If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0, If LOC, MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0,
we don't store that info. */ we don't store that info. */
const char * const char *
@ -1603,6 +1618,12 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
} }
nbase = i; nbase = i;
} }
else if (GET_CODE (asmop) == ASM_INPUT)
{
if (loc)
*loc = ASM_INPUT_SOURCE_LOCATION (asmop);
return XSTR (asmop, 0);
}
break; break;
} }
@ -2245,7 +2266,8 @@ extract_insn (rtx_insn *insn)
case PARALLEL: case PARALLEL:
if ((GET_CODE (XVECEXP (body, 0, 0)) == SET if ((GET_CODE (XVECEXP (body, 0, 0)) == SET
&& GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS) && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
|| GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) || GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS
|| GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
goto asm_insn; goto asm_insn;
else else
goto normal_insn; goto normal_insn;

View File

@ -1,3 +1,8 @@
2016-06-06 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR c/24414
* gcc.target/i386/pr24414.c: New test.
2016-06-06 Jose E. Marchesi <jose.marchesi@oracle.com> 2016-06-06 Jose E. Marchesi <jose.marchesi@oracle.com>
* gcc.target/sparc/vis4misc.c: New file. * gcc.target/sparc/vis4misc.c: New file.

View File

@ -0,0 +1,13 @@
/* { dg-do run } */
/* { dg-options "-O2" } */
int test;
int
main ()
{
int x = test;
asm ("movl $1,test");
if (x + test != 1)
__builtin_trap ();
return 0;
}