Hi,
from the recent discussion on g...@gcc.gnu.org I became aware that the so
called "basic asm"
which is an asm without colon, has no way to specify the clobber list. That
makes it rather
useless, because everyone would expect it to be able to use at least global
memory.
Furthermore there is a target hook that allows extended asm to implicitly
clobber the "cc" register
on certain targets. This hook should also be called for basic asm, because
nobody would expect to
have to preserve that on a basic asm. But I would say it is naturally clear
that if the basic asm
would clobber any general purpose register the previous value must be pushed by
the assembler
code and restored at the end.
Furthermore there is a documented use for asm(""): The empty assembler string
is used to make a function
volatile, thus calls can not be optimized away. But I think it is not
necessary to make this clobber anything,
nor should it be an instruction scheduling barrier, as it used to be in the
past.
The attached patch implements this by introducing a new parallel block for
asm_input with clobbers.
I believe it is quite safe, and will not break any existing code.
It was boot-strapped and regression-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?
... or should I wait for the next stage1?
Thanks
Bernd.gcc:
2015-12-09 Bernd Edlinger
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.
* gimple.c (gimple_asm_clobbers_memory_p): Handle basic asm with
non-empty assembler string.
* final.c (final_scan_insn): Handle basic asm in PARALLEL block.
* 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.
* sched-deps.c (sched_analyze_2): Make no barrier for basic asm with
empty assembler string.
* doc/extend.texi: Mention new behavior of basic asm.
testsuite:
2015-12-09 Bernd Edlinger
PR c/24414
* gcc.target/i386/pr24414.c: New test.
Index: gcc/cfgexpand.c
===
--- gcc/cfgexpand.c (revision 231412)
+++ gcc/cfgexpand.c (working copy)
@@ -2655,9 +2655,6 @@ expand_asm_loc (tree string, int vol, location_t l
{
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);
@@ -2664,6 +2661,34 @@ expand_asm_loc (tree string, int vol, location_t l
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 input_rvec, output_rvec;
+ auto_vec constraints;
+ auto_vec 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);
}
Index: gcc/doc/extend.texi
===
--- gcc/doc/extend.texi (revision 231412)
+++ gcc/doc/extend.texi (working copy)
@@ -7442,6 +7442,10 @@ all basic @code{asm} blocks use the assembler dial
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
Index: gcc/final.c
===
--- gcc/final.c (revision 231412)
+++ gcc/final.c (working copy)
@@ -2565,6 +2565,10 @@ final_scan_insn (rtx_insn *insn, FILE *file, int o
(*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);
Index: gcc/gimple.c