asm inline
authorSegher Boessenkool <segher@kernel.crashing.org>
Thu, 6 Dec 2018 17:56:58 +0000 (18:56 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Thu, 6 Dec 2018 17:56:58 +0000 (18:56 +0100)
The Linux kernel people want a feature that makes GCC pretend some
inline assembler code is tiny (while it would think it is huge), so
that such code will be inlined essentially always instead of
essentially never.

This patch lets you say "asm inline" instead of just "asm", with the
result that that inline assembler is always counted as minimum cost
for inlining.  It implements this for C and C++, making "inline"
another asm-qualifier (supplementing "volatile" and "goto").

* doc/extend.texi (Using Assembly Language with C): Document asm inline.
(Size of an asm): Fix typo.  Document asm inline.
* gimple-pretty-print.c (dump_gimple_asm): Handle asm inline.
* gimple.h (enum gf_mask): Add GF_ASM_INLINE.
(gimple_asm_set_volatile): Fix typo.
(gimple_asm_inline_p): New.
(gimple_asm_set_inline): New.
* gimplify.c (gimplify_asm_expr): Propagate the asm inline flag from
tree to gimple.
* ipa-icf-gimple.c (func_checker::compare_gimple_asm): Compare the
gimple_asm_inline_p flag, too.
* tree-core.h (tree_base): Document that protected_flag is ASM_INLINE_P
in an ASM_EXPR.
* tree-inline.c (estimate_num_insns): If gimple_asm_inline_p return
a minimum size for an asm.
* tree.h (ASM_INLINE_P): New.

gcc/c/
* c-parser.c (c_parser_asm_statement): Detect the inline keyword
after asm.  Pass a flag for it to build_asm_expr.
* c-tree.h (build_asm_expr): Update declaration.
* c-typeck.c (build_asm_stmt): Add is_inline parameter.  Use it to
set ASM_INLINE_P.

gcc/cp/
* cp-tree.h (finish_asm_stmt): Update declaration.
* parser.c (cp_parser_asm_definition): Detect the inline keyword
after asm.  Pass a flag for it to finish_asm_stmt.
* pt.c (tsubst_expr): Pass the ASM_INLINE_P flag to finish_asm_stmt.
* semantics.c (finish_asm_stmt): Add inline_p parameter.  Use it to
set ASM_INLINE_P.

gcc/testsuite/
* c-c++-common/torture/asm-inline.c: New testcase.
* gcc.dg/asm-qual-2.c: Test asm inline, too.

From-SVN: r266860

21 files changed:
gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/c/c-tree.h
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/doc/extend.texi
gcc/gimple-pretty-print.c
gcc/gimple.h
gcc/gimplify.c
gcc/ipa-icf-gimple.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/torture/asm-inline.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-qual-2.c
gcc/tree-core.h
gcc/tree-inline.c
gcc/tree.h

index acf327cd8ca6832dd4c35f36eb8e15a36dd7d17b..8789afacbaff0a9eb925018dc84b9a4f82a1a7e7 100644 (file)
@@ -1,3 +1,22 @@
+2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * doc/extend.texi (Using Assembly Language with C): Document asm inline.
+       (Size of an asm): Fix typo.  Document asm inline.
+       * gimple-pretty-print.c (dump_gimple_asm): Handle asm inline.
+       * gimple.h (enum gf_mask): Add GF_ASM_INLINE.
+       (gimple_asm_set_volatile): Fix typo.
+       (gimple_asm_inline_p): New.
+       (gimple_asm_set_inline): New.
+       * gimplify.c (gimplify_asm_expr): Propagate the asm inline flag from
+       tree to gimple.
+       * ipa-icf-gimple.c (func_checker::compare_gimple_asm): Compare the
+       gimple_asm_inline_p flag, too.
+       * tree-core.h (tree_base): Document that protected_flag is ASM_INLINE_P
+       in an ASM_EXPR.
+       * tree-inline.c (estimate_num_insns): If gimple_asm_inline_p return
+       a minimum size for an asm.
+       * tree.h (ASM_INLINE_P): New.
+
 2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
 
        PR inline-asm/55681
index c54223de26d2e3b7e5eda204f5c5f1254f4e635f..69d4929624b9ba7905e73f31b78ad7f20146ce4f 100644 (file)
@@ -1,3 +1,11 @@
+2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-parser.c (c_parser_asm_statement): Detect the inline keyword
+       after asm.  Pass a flag for it to build_asm_expr.
+       * c-tree.h (build_asm_expr): Update declaration.
+       * c-typeck.c (build_asm_stmt): Add is_inline parameter.  Use it to
+       set ASM_INLINE_P.
+
 2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
 
        PR inline-asm/55681
index a4a8745acffb1d391e74b6ab80c6c42eb94dd429..3a7fcdce33b59c52568a39ebc18c3a9fdb2502f3 100644 (file)
@@ -6329,11 +6329,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
 }
 
 /* Parse an asm statement, a GNU extension.  This is a full-blown asm
-   statement with inputs, outputs, clobbers, and volatile and goto tag
-   allowed.
+   statement with inputs, outputs, clobbers, and volatile, inline, and goto
+   tags allowed.
 
    asm-qualifier:
      volatile
+     inline
      goto
 
    asm-qualifier-list:
@@ -6360,7 +6361,7 @@ static tree
 c_parser_asm_statement (c_parser *parser)
 {
   tree quals, str, outputs, inputs, clobbers, labels, ret;
-  bool simple, is_volatile, is_goto;
+  bool simple, is_volatile, is_inline, is_goto;
   location_t asm_loc = c_parser_peek_token (parser)->location;
   int section, nsections;
 
@@ -6369,6 +6370,7 @@ c_parser_asm_statement (c_parser *parser)
 
   quals = NULL_TREE;
   is_volatile = false;
+  is_inline = false;
   is_goto = false;
   for (bool done = false; !done; )
     switch (c_parser_peek_token (parser)->keyword)
@@ -6383,6 +6385,16 @@ c_parser_asm_statement (c_parser *parser)
        else
          done = true;
        break;
+      case RID_INLINE:
+       if (!is_inline)
+         {
+           is_inline = true;
+           quals = c_parser_peek_token (parser)->value;
+           c_parser_consume_token (parser);
+         }
+       else
+         done = true;
+       break;
       case RID_GOTO:
        if (!is_goto)
          {
@@ -6471,7 +6483,8 @@ c_parser_asm_statement (c_parser *parser)
     c_parser_skip_to_end_of_block_or_statement (parser);
 
   ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
-                                              clobbers, labels, simple));
+                                              clobbers, labels, simple,
+                                              is_inline));
 
  error:
   parser->lex_untranslated_string = false;
index 5ed2f48f763ba274b0ba67337d5f09375468b6ab..f08a8fc8bcc4c8f62fe525151b7768f514aa7a83 100644 (file)
@@ -677,7 +677,8 @@ extern tree build_compound_literal (location_t, tree, tree, bool,
 extern void check_compound_literal_type (location_t, struct c_type_name *);
 extern tree c_start_case (location_t, location_t, tree, bool);
 extern void c_finish_case (tree, tree);
-extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool);
+extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool,
+                           bool);
 extern tree build_asm_stmt (tree, tree);
 extern int c_types_compatible_p (tree, tree);
 extern tree c_begin_compound_stmt (bool);
index 8fbecfce956c0d55ebe19ccacd50eba17fe9fc26..1a89727308885c98c13f5d7d9a9da45efc20eee3 100644 (file)
@@ -10327,10 +10327,12 @@ build_asm_stmt (tree cv_qualifier, tree args)
    some INPUTS, and some CLOBBERS.  The latter three may be NULL.
    SIMPLE indicates whether there was anything at all after the
    string in the asm expression -- asm("blah") and asm("blah" : )
-   are subtly different.  We use a ASM_EXPR node to represent this.  */
+   are subtly different.  We use a ASM_EXPR node to represent this.
+   LOC is the location of the asm, and IS_INLINE says whether this
+   is asm inline.  */
 tree
 build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
-               tree clobbers, tree labels, bool simple)
+               tree clobbers, tree labels, bool simple, bool is_inline)
 {
   tree tail;
   tree args;
@@ -10448,6 +10450,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
      as volatile.  */
   ASM_INPUT_P (args) = simple;
   ASM_VOLATILE_P (args) = (noutputs == 0);
+  ASM_INLINE_P (args) = is_inline;
 
   return args;
 }
index 26b83cffdff88cf9a82a520a4312173d8fc9c5ba..89f2d8896abe1c858a867c809b01010a709e3f4b 100644 (file)
@@ -1,3 +1,12 @@
+2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * cp-tree.h (finish_asm_stmt): Update declaration.
+       * parser.c (cp_parser_asm_definition): Detect the inline keyword
+       after asm.  Pass a flag for it to finish_asm_stmt.
+       * pt.c (tsubst_expr): Pass the ASM_INLINE_P flag to finish_asm_stmt.
+       * semantics.c (finish_asm_stmt): Add inline_p parameter.  Use it to
+       set ASM_INLINE_P.
+
 2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
 
        PR inline-asm/55681
index c1f99315b06dbaf0e6103f2a65b377864e0a001e..636e53aa3919a73cd27b81339a9b5238850e33e3 100644 (file)
@@ -6997,7 +6997,7 @@ extern tree begin_compound_stmt                   (unsigned int);
 
 extern void finish_compound_stmt               (tree);
 extern tree finish_asm_stmt                    (int, tree, tree, tree, tree,
-                                                tree);
+                                                tree, bool);
 extern tree finish_label_stmt                  (tree);
 extern void finish_label_decl                  (tree);
 extern cp_expr finish_parenthesized_expr       (cp_expr);
index ac953d0c61119c5751d41d677f3299bfd1469644..ceae72a7709e7d0fe8308631a0897b0407caa5b7 100644 (file)
@@ -19592,6 +19592,7 @@ cp_parser_using_directive (cp_parser* parser)
 
   asm-qualifier:
     volatile
+    inline
     goto
 
   asm-qualifier-list:
@@ -19632,6 +19633,7 @@ cp_parser_asm_definition (cp_parser* parser)
   bool extended_p = false;
   bool invalid_inputs_p = false;
   bool invalid_outputs_p = false;
+  bool inline_p = false;
   bool goto_p = false;
   required_token missing = RT_NONE;
 
@@ -19661,6 +19663,17 @@ cp_parser_asm_definition (cp_parser* parser)
          else
            done = true;
          break;
+       case RID_INLINE:
+         if (!inline_p && parser->in_function_body)
+           {
+             /* Remember that we saw the `inline' keyword.  */
+             inline_p = true;
+             /* Consume the token.  */
+             cp_lexer_consume_token (parser->lexer);
+           }
+         else
+           done = true;
+         break;
        case RID_GOTO:
          if (!goto_p && parser->in_function_body)
            {
@@ -19802,7 +19815,7 @@ cp_parser_asm_definition (cp_parser* parser)
       if (parser->in_function_body)
        {
          asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
-                                     inputs, clobbers, labels);
+                                     inputs, clobbers, labels, inline_p);
          /* If the extended syntax was not used, mark the ASM_EXPR.  */
          if (!extended_p)
            {
index 78addc6c1c2e2566d160e9cac3c4490860e2b8f9..90fb3aee82d4ad94b1109ad4e2ea4c10fde46241 100644 (file)
@@ -17220,7 +17220,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
        tree labels = tsubst_copy_asm_operands (ASM_LABELS (t), args,
                                                complain, in_decl);
        tmp = finish_asm_stmt (ASM_VOLATILE_P (t), string, outputs, inputs,
-                              clobbers, labels);
+                              clobbers, labels, ASM_INLINE_P (t));
        tree asm_expr = tmp;
        if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
          asm_expr = TREE_OPERAND (asm_expr, 0);
index 733c42f00368ef463eb468b3897942faa0fd7a19..c1240cce1e16a2239381a61e84709327e27d316c 100644 (file)
@@ -1482,11 +1482,11 @@ finish_compound_stmt (tree stmt)
 /* Finish an asm-statement, whose components are a STRING, some
    OUTPUT_OPERANDS, some INPUT_OPERANDS, some CLOBBERS and some
    LABELS.  Also note whether the asm-statement should be
-   considered volatile.  */
+   considered volatile, and whether it is asm inline.  */
 
 tree
 finish_asm_stmt (int volatile_p, tree string, tree output_operands,
-                tree input_operands, tree clobbers, tree labels)
+                tree input_operands, tree clobbers, tree labels, bool inline_p)
 {
   tree r;
   tree t;
@@ -1640,6 +1640,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
                  output_operands, input_operands,
                  clobbers, labels);
   ASM_VOLATILE_P (r) = volatile_p || noutputs == 0;
+  ASM_INLINE_P (r) = inline_p;
   r = maybe_cleanup_point_expr_void (r);
   return add_stmt (r);
 }
index 70c46cff5691e9d76364b2289b4fbf9105e3dd1b..7700ab95160fd2f857b8fe92efff93b1ea8d40a5 100644 (file)
@@ -8460,6 +8460,10 @@ various @option{-std} options, use @code{__asm__} instead of
 @item volatile
 The optional @code{volatile} qualifier has no effect. 
 All basic @code{asm} blocks are implicitly volatile.
+
+@item inline
+If you use the @code{inline} qualifier, then for inlining purposes the size
+of the asm is taken as the smallest size possible (@pxref{Size of an asm}).
 @end table
 
 @subsubheading Parameters
@@ -8603,6 +8607,10 @@ values to produce output values. However, your @code{asm} statements may
 also produce side effects. If so, you may need to use the @code{volatile} 
 qualifier to disable certain optimizations. @xref{Volatile}.
 
+@item inline
+If you use the @code{inline} qualifier, then for inlining purposes the size
+of the asm is taken as the smallest size possible (@pxref{Size of an asm}).
+
 @item goto
 This qualifier informs the compiler that the @code{asm} statement may 
 perform a jump to one of the labels listed in the @var{GotoLabels}.
@@ -10061,7 +10069,7 @@ does this by counting the number of instructions in the pattern of the
 @code{asm} and multiplying that by the length of the longest
 instruction supported by that processor.  (When working out the number
 of instructions, it assumes that any occurrence of a newline or of
-whatever statement separator character is supported by the assembler --
+whatever statement separator character is supported by the assembler ---
 typically @samp{;} --- indicates the end of an instruction.)
 
 Normally, GCC's estimate is adequate to ensure that correct
@@ -10072,6 +10080,11 @@ space in the object file than is needed for a single instruction.
 If this happens then the assembler may produce a diagnostic saying that
 a label is unreachable.
 
+@cindex @code{asm inline}
+This size is also used for inlining decisions.  If you use @code{asm inline}
+instead of just @code{asm}, then for inlining purposes the size of the asm
+is taken as the minimum size, ignoring how many instructions GCC thinks it is.
+
 @node Alternate Keywords
 @section Alternate Keywords
 @cindex alternate keywords
index 276e5798baced46fe2a112732abd4d6da139e092..51c0fb33f2f94ee6e88ac3a0268794e4fad8ae20 100644 (file)
@@ -2048,6 +2048,8 @@ dump_gimple_asm (pretty_printer *buffer, gasm *gs, int spc, dump_flags_t flags)
       pp_string (buffer, "__asm__");
       if (gimple_asm_volatile_p (gs))
        pp_string (buffer, " __volatile__");
+      if (gimple_asm_inline_p (gs))
+       pp_string (buffer, " __inline__");
       if (gimple_asm_nlabels (gs))
        pp_string (buffer, " goto");
       pp_string (buffer, "(\"");
index 9853521f984d035137ba481cba4e0201ca7c0a69..37fd5fb9ac3822584b069af5032e91d137317ec0 100644 (file)
@@ -137,6 +137,7 @@ enum gimple_rhs_class
 enum gf_mask {
     GF_ASM_INPUT               = 1 << 0,
     GF_ASM_VOLATILE            = 1 << 1,
+    GF_ASM_INLINE              = 1 << 2,
     GF_CALL_FROM_THUNK         = 1 << 0,
     GF_CALL_RETURN_SLOT_OPT    = 1 << 1,
     GF_CALL_TAILCALL           = 1 << 2,
@@ -3911,7 +3912,7 @@ gimple_asm_string (const gasm *asm_stmt)
 }
 
 
-/* Return true ASM_STMT ASM_STMT is an asm statement marked volatile.  */
+/* Return true if ASM_STMT is marked volatile.  */
 
 static inline bool
 gimple_asm_volatile_p (const gasm *asm_stmt)
@@ -3920,7 +3921,7 @@ gimple_asm_volatile_p (const gasm *asm_stmt)
 }
 
 
-/* If VOLATLE_P is true, mark asm statement ASM_STMT as volatile.  */
+/* If VOLATILE_P is true, mark asm statement ASM_STMT as volatile.  */
 
 static inline void
 gimple_asm_set_volatile (gasm *asm_stmt, bool volatile_p)
@@ -3932,6 +3933,27 @@ gimple_asm_set_volatile (gasm *asm_stmt, bool volatile_p)
 }
 
 
+/* Return true if ASM_STMT is marked inline.  */
+
+static inline bool
+gimple_asm_inline_p (const gasm *asm_stmt)
+{
+  return (asm_stmt->subcode & GF_ASM_INLINE) != 0;
+}
+
+
+/* If INLINE_P is true, mark asm statement ASM_STMT as inline.  */
+
+static inline void
+gimple_asm_set_inline (gasm *asm_stmt, bool inline_p)
+{
+  if (inline_p)
+    asm_stmt->subcode |= GF_ASM_INLINE;
+  else
+    asm_stmt->subcode &= ~GF_ASM_INLINE;
+}
+
+
 /* If INPUT_P is true, mark asm ASM_STMT as an ASM_INPUT.  */
 
 static inline void
index d96ee43e7deedc2ecc546641c9b49f5f9d96f4ab..9022ef8b2ee6575fb011012fa76792f9ebbf0c20 100644 (file)
@@ -6361,6 +6361,7 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
       gimple_asm_set_volatile (stmt, ASM_VOLATILE_P (expr) || noutputs == 0);
       gimple_asm_set_input (stmt, ASM_INPUT_P (expr));
+      gimple_asm_set_inline (stmt, ASM_INLINE_P (expr));
 
       gimplify_seq_add_stmt (pre_p, stmt);
     }
index ba39ea365740249a5c0c71ca1fcc9364058a274a..5361139498889a147f5d85e3e50982be06671609 100644 (file)
@@ -993,6 +993,9 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
   if (gimple_asm_input_p (g1) != gimple_asm_input_p (g2))
     return false;
 
+  if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2))
+    return false;
+
   if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
     return false;
 
index 11152d0ae3047aa6ec307ad12a882520b726106b..f95ef6103d2689f9036e61d8304d47a1cc80a19c 100644 (file)
@@ -1,3 +1,8 @@
+2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-c++-common/torture/asm-inline.c: New testcase.
+       * gcc.dg/asm-qual-2.c: Test asm inline, too.
+
 2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
 
        PR inline-asm/55681
diff --git a/gcc/testsuite/c-c++-common/torture/asm-inline.c b/gcc/testsuite/c-c++-common/torture/asm-inline.c
new file mode 100644 (file)
index 0000000..dea8965
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* -O0 does no inlining, and -O3 does it too aggressively for this test:  */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O3" } { "" } }
+/* The normal asm is not inlined:  */
+/* { dg-final { scan-assembler-times "w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w" 2 } } */
+/* But the asm inline is inlined:  */
+/* { dg-final { scan-assembler-times "x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x" 8 } } */
+
+static void f(void)
+{
+  asm ("w\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\n"
+       "w\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw");
+}
+
+int f0(void) { f(); return 0; }
+int f1(void) { f(); return 1; }
+int f2(void) { f(); return 2; }
+int f3(void) { f(); return 3; }
+
+static void fg(void)
+{
+  asm goto("w\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\n"
+          "w\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw" :::: q);
+  q: ;
+}
+
+int fg0(void) { fg(); return 0; }
+int fg1(void) { fg(); return 1; }
+int fg2(void) { fg(); return 2; }
+int fg3(void) { fg(); return 3; }
+
+static void g(void)
+{
+  asm inline("x\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\n"
+            "x\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx");
+}
+
+int g0(void) { g(); return 0; }
+int g1(void) { g(); return 1; }
+int g2(void) { g(); return 2; }
+int g3(void) { g(); return 3; }
+
+static void gg(void)
+{
+  asm inline goto("x\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\n"
+                 "x\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx" :::: q);
+  q: ;
+}
+
+int gg0(void) { gg(); return 0; }
+int gg1(void) { gg(); return 1; }
+int gg2(void) { gg(); return 2; }
+int gg3(void) { gg(); return 3; }
index 37df2ad2b8d86915726d341ca87411c565f95669..79135c3d2f2f2ebf77bd3a8ddc078a714d708ed8 100644 (file)
@@ -6,7 +6,18 @@ void
 f (void)
 {
   asm volatile goto ("" :::: lab);
+  asm volatile inline ("" :::);
+  asm inline volatile ("" :::);
+  asm inline goto ("" :::: lab);
   asm goto volatile ("" :::: lab);
+  asm goto inline ("" :::: lab);
+
+  asm volatile inline goto ("" :::: lab);
+  asm volatile goto inline ("" :::: lab);
+  asm inline volatile goto ("" :::: lab);
+  asm inline goto volatile ("" :::: lab);
+  asm goto volatile inline ("" :::: lab);
+  asm goto inline volatile ("" :::: lab);
 
   /* Duplicates are not allowed.  */
   asm goto volatile volatile ("" :::: lab);  /* { dg-error "" } */
@@ -16,6 +27,20 @@ f (void)
   asm goto volatile goto ("" :::: lab);  /* { dg-error "" } */
   asm volatile goto goto ("" :::: lab);  /* { dg-error "" } */
 
+  asm inline volatile volatile ("" :::);  /* { dg-error "" } */
+  asm volatile inline volatile ("" :::);  /* { dg-error "" } */
+  asm volatile volatile inline ("" :::);  /* { dg-error "" } */
+  asm inline inline volatile ("" :::);  /* { dg-error "" } */
+  asm inline volatile inline ("" :::);  /* { dg-error "" } */
+  asm volatile inline inline ("" :::);  /* { dg-error "" } */
+
+  asm goto inline inline ("" :::: lab);  /* { dg-error "" } */
+  asm inline goto inline ("" :::: lab);  /* { dg-error "" } */
+  asm inline inline goto ("" :::: lab);  /* { dg-error "" } */
+  asm goto goto inline ("" :::: lab);  /* { dg-error "" } */
+  asm goto inline goto ("" :::: lab);  /* { dg-error "" } */
+  asm inline goto goto ("" :::: lab);  /* { dg-error "" } */
+
 lab:
   ;
 }
index cec95e72c54efca9783c7397ba895cd2a32485ba..e7646afe117aef231f43b06032f31b06ee679b32 100644 (file)
@@ -1193,6 +1193,9 @@ struct GTY(()) tree_base {
        OMP_CLAUSE_LINEAR_VARIABLE_STRIDE in
           OMP_CLAUSE_LINEAR
 
+       ASM_INLINE_P in
+          ASM_EXPR
+
    side_effects_flag:
 
        TREE_SIDE_EFFECTS in
index 5aa782b1edbdca06d68f60d5583c18a88ba781e1..52f0310021e558813694d6a98ad56663cfb9d563 100644 (file)
@@ -4109,6 +4109,9 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
           with very long asm statements.  */
        if (count > 1000)
          count = 1000;
+       /* If this asm is asm inline, count anything as minimum size.  */
+       if (gimple_asm_inline_p (as_a <gasm *> (stmt)))
+         count = MIN (1, count);
        return MAX (1, count);
       }
 
index 960526d48a8dbea38dc74bfc171162ccdf238d90..761b5083d4d8b02ae6ae779714b7dee298f67892 100644 (file)
@@ -1245,6 +1245,9 @@ extern tree maybe_wrap_with_location (tree, location_t);
    ASM_OPERAND with no operands.  */
 #define ASM_INPUT_P(NODE) (ASM_EXPR_CHECK (NODE)->base.static_flag)
 #define ASM_VOLATILE_P(NODE) (ASM_EXPR_CHECK (NODE)->base.public_flag)
+/* Nonzero if we want to consider this asm as minimum length and cost
+   for inlining decisions.  */
+#define ASM_INLINE_P(NODE) (ASM_EXPR_CHECK (NODE)->base.protected_flag)
 
 /* COND_EXPR accessors.  */
 #define COND_EXPR_COND(NODE)   (TREE_OPERAND (COND_EXPR_CHECK (NODE), 0))