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>
* 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;
if (TREE_CODE (string) == ADDR_EXPR)
string = TREE_OPERAND (string, 0);
body = gen_rtx_ASM_INPUT_loc (VOIDmode,
ggc_strdup (TREE_STRING_POINTER (string)),
locus);
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);
}

View file

@ -162,7 +162,7 @@ arithmetic_flags_clobber_p (rtx_insn *insn)
if (!NONJUMP_INSN_P (insn))
return false;
pat = PATTERN (insn);
if (extract_asm_operands (pat))
if (asm_noperands (pat) >= 0)
return false;
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 CALL:
case ASM_OPERANDS:
case ASM_INPUT:
need_barrier |= rtx_needs_barrier (pat, flags, pred);
break;

View file

@ -6442,7 +6442,7 @@ branch_to_delay_slot_p (rtx_insn *insn)
the branch is followed by an asm. */
if (!insn
|| GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX
|| asm_noperands (PATTERN (insn)) >= 0
|| get_attr_length (insn) > 0)
break;
}
@ -6473,7 +6473,7 @@ branch_needs_nop_p (rtx_insn *insn)
return TRUE;
if (!(GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX)
|| asm_noperands (PATTERN (insn)) >= 0)
&& get_attr_length (insn) > 0)
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. */
if (!insn
|| GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX)
|| asm_noperands (PATTERN (insn)) >= 0)
break;
if (get_attr_length (insn) == 4
&& 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
discard them as unreferenced. It also does not know about side effects of
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.
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
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:
@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,
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)
{
const char *string = XSTR (body, 0);

View file

@ -2583,6 +2583,10 @@ gimple_asm_clobbers_memory_p (const gasm *stmt)
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;
}

View file

@ -2233,7 +2233,7 @@ compute_regs_asm_clobbered (void)
{
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)
{
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,
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. */
int
asm_noperands (const_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)
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)
n_sets = 1;
else if (GET_CODE (body) == PARALLEL)
{
int i;
if (GET_CODE (XVECEXP (body, 0, 0)) == SET)
{
/* 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,
and the constraints for the operands into CONSTRAINTS.
Write the modes of the operands into MODES.
Write the location info into LOC.
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. */
const char *
@ -1603,6 +1618,12 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
}
nbase = i;
}
else if (GET_CODE (asmop) == ASM_INPUT)
{
if (loc)
*loc = ASM_INPUT_SOURCE_LOCATION (asmop);
return XSTR (asmop, 0);
}
break;
}
@ -2245,7 +2266,8 @@ extract_insn (rtx_insn *insn)
case PARALLEL:
if ((GET_CODE (XVECEXP (body, 0, 0)) == SET
&& 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;
else
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>
* 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;
}