re PR c/24414 (Old-style asms don't clobber memory)
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Mon, 6 Jun 2016 12:31:59 +0000 (12:31 +0000)
committerBernd Edlinger <edlinger@gcc.gnu.org>
Mon, 6 Jun 2016 12:31:59 +0000 (12:31 +0000)
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

12 files changed:
gcc/ChangeLog
gcc/cfgexpand.c
gcc/compare-elim.c
gcc/config/ia64/ia64.c
gcc/config/pa/pa.c
gcc/doc/extend.texi
gcc/final.c
gcc/gimple.c
gcc/ira.c
gcc/recog.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr24414.c [new file with mode: 0644]

index a0255b1d3990ca160bcac3a592234ff14087fadf..3bffb744b8d5b1985247504952c91e71c99bc110 100644 (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.
index 56ef71dfbabb73108b35340a99099e4168a0547e..e4ddb3aac9fdd56c0a96b3bc2f7a69ce578f8c21 100644 (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);
 }
 
index a5ce2bfcf2c023c7996a9f2f9b9069a974d648bd..e7fdce83734a84fb107ae05c7a72aa0b0e1a3952 100644 (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)
index 742123f401e044bdb593775ebf2da4093e8ca9cd..7f439d3fe82f644023c2f1f8ea7cba89d5a942d7 100644 (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;
 
index 8b1c8327c79733b09716344938cd243c31ed2c5c..a78405ab792578551dcfb1404c7a8dff6b63b373 100644 (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))
index c85e6dbb5fe39628e83de68e51f066e8bf08109c..7208f33e76c9b508d7fa658dc31b12c57e4fcea6 100644 (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
index 55cf509611f7bc61246c63a6e997bd7402dd8428..5b04311218e29432dd29bebec06438a92abbb066 100644 (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);
index 226b080107289def522ddfea247c5f6aa3bf9114..75a1ed8ee0ba71c754647f0a346e176a5d029f52 100644 (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;
 }
 
index 3c4e3b6bd083cfdf6a8604e0c9f611f194334aa1..c66bb9e78fc99d57f52054ad5861f768893306df 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -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);
index 92b2aa31a777b60bfd2f725d2c5d51006b971fbe..80d1779f7e1eeb453ecd19fb3bf178383216158e 100644 (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;
index e5d1407c9e33c50fefe2d3cc1e7372a926a01347..0940e916b1667dfa3ab1cc54b247e56c9ab1a03f 100644 (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.
diff --git a/gcc/testsuite/gcc.target/i386/pr24414.c b/gcc/testsuite/gcc.target/i386/pr24414.c
new file mode 100644 (file)
index 0000000..bd12f0c
--- /dev/null
@@ -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;
+}