compiler: support inlining functions with if statements
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 7 Jun 2019 14:19:51 +0000 (14:19 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 7 Jun 2019 14:19:51 +0000 (14:19 +0000)
    This increases the number of inlinable functions from 455 to 500.
    An example of a newly inlinable function is strings.Compare.

    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/181137

From-SVN: r272045

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/statements.cc
gcc/go/gofrontend/statements.h

index 428b59a08fedaff5b8dbef71c6b5a45b79e135b9..e107d529eb66b22c7d121559dbd92724dbe50719 100644 (file)
@@ -1,4 +1,4 @@
-46329dd9e6473fff46df6b310c11116d1558e470
+9df825b5f142ac2b6f48a8dac94fcff740acd411
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 480077823d1ade7e92b3c628cb3ba8261c83cbb7..6d51d9e0c9082658c0dd59387f93ca69a310a7f9 100644 (file)
@@ -6941,7 +6941,12 @@ Block::import_block(Block* set, Import_function_body *ifb, Location loc)
 
       if (at_end)
        {
-         off = nl + 1;
+         // An if statement can have an "else" following the "}", in
+         // which case we want to leave the offset where it is, just
+         // after the "}".  We don't get the block ending location
+         // quite right for if statements.
+         if (body.compare(off, 6, " else ") != 0)
+           off = nl + 1;
          break;
        }
 
index cd7b8568a1285a73851d4af9d2050a88e7359ff1..f680a0a1c3e079e120e662804546e8dfbb984b14 100644 (file)
@@ -129,22 +129,8 @@ Statement::import_statement(Import_function_body* ifb, Location loc)
 {
   if (ifb->match_c_string("{"))
     {
-      size_t nl = ifb->body().find('\n', ifb->off());
-      if (nl == std::string::npos)
-       {
-         if (!ifb->saw_error())
-           go_error_at(ifb->location(),
-                       "import error: no newline after { at %lu",
-                       static_cast<unsigned long>(ifb->off()));
-         ifb->set_saw_error();
-         return Statement::make_error_statement(loc);
-       }
-      ifb->set_off(nl + 1);
-      ifb->increment_indent();
-      Block* block = new Block(ifb->block(), loc);
-      bool ok = Block::import_block(block, ifb, loc);
-      ifb->decrement_indent();
-      if (!ok)
+      Block* block = Block_statement::do_import(ifb, loc);
+      if (block == NULL)
        return Statement::make_error_statement(loc);
       return Statement::make_block_statement(block, loc);
     }
@@ -159,6 +145,8 @@ Statement::import_statement(Import_function_body* ifb, Location loc)
     return Temporary_statement::do_import(ifb, loc);
   else if (ifb->match_c_string("var "))
     return Variable_declaration_statement::do_import(ifb, loc);
+  else if (ifb->match_c_string("if "))
+    return If_statement::do_import(ifb, loc);
 
   Expression* lhs = Expression::import_expression(ifb, loc);
   ifb->require_c_string(" = ");
@@ -2120,14 +2108,20 @@ Statement::make_statement(Expression* expr, bool is_ignored)
 
 void
 Block_statement::do_export_statement(Export_function_body* efb)
+{
+  Block_statement::export_block(efb, this->block_);
+}
+
+void
+Block_statement::export_block(Export_function_body* efb, Block* block)
 {
   // We are already indented to the right position.
   char buf[50];
   snprintf(buf, sizeof buf, "{ //%d\n",
-          Linemap::location_to_line(this->block_->start_location()));
+          Linemap::location_to_line(block->start_location()));
   efb->write_c_string(buf);
 
-  this->block_->export_block(efb);
+  block->export_block(efb);
   // The indentation is correct for the statements in the block, so
   // subtract one for the closing curly brace.
   efb->decrement_indent();
@@ -2137,6 +2131,32 @@ Block_statement::do_export_statement(Export_function_body* efb)
   efb->increment_indent();
 }
 
+// Import a block statement, returning the block.
+
+Block*
+Block_statement::do_import(Import_function_body* ifb, Location loc)
+{
+  go_assert(ifb->match_c_string("{"));
+  size_t nl = ifb->body().find('\n', ifb->off());
+  if (nl == std::string::npos)
+    {
+      if (!ifb->saw_error())
+       go_error_at(ifb->location(),
+                   "import error: no newline after { at %lu",
+                   static_cast<unsigned long>(ifb->off()));
+      ifb->set_saw_error();
+      return NULL;
+    }
+  ifb->set_off(nl + 1);
+  ifb->increment_indent();
+  Block* block = new Block(ifb->block(), loc);
+  bool ok = Block::import_block(block, ifb, loc);
+  ifb->decrement_indent();
+  if (!ok)
+    return NULL;
+  return block;
+}
+
 // Convert a block to the backend representation of a statement.
 
 Bstatement*
@@ -3529,6 +3549,73 @@ If_statement::do_get_backend(Translate_context* context)
                                          this->location());
 }
 
+// Export an if statement.
+
+void
+If_statement::do_export_statement(Export_function_body* efb)
+{
+  efb->write_c_string("if ");
+  this->cond_->export_expression(efb);
+  efb->write_c_string(" ");
+  Block_statement::export_block(efb, this->then_block_);
+  if (this->else_block_ != NULL)
+    {
+      efb->write_c_string(" else ");
+      Block_statement::export_block(efb, this->else_block_);
+    }
+}
+
+// Import an if statement.
+
+Statement*
+If_statement::do_import(Import_function_body* ifb, Location loc)
+{
+  ifb->require_c_string("if ");
+
+  Expression* cond = Expression::import_expression(ifb, loc);
+  Type_context context(Type::lookup_bool_type(), false);
+  cond->determine_type(&context);
+  ifb->require_c_string(" ");
+
+  if (!ifb->match_c_string("{"))
+    {
+      if (!ifb->saw_error())
+       go_error_at(ifb->location(),
+                   "import error for %qs: no block for if statement at %lu",
+                   ifb->name().c_str(),
+                   static_cast<unsigned long>(ifb->off()));
+      ifb->set_saw_error();
+      return Statement::make_error_statement(loc);
+    }
+
+  Block* then_block = Block_statement::do_import(ifb, loc);
+  if (then_block == NULL)
+    return Statement::make_error_statement(loc);
+
+  Block* else_block = NULL;
+  if (ifb->match_c_string(" else "))
+    {
+      ifb->advance(6);
+      if (!ifb->match_c_string("{"))
+       {
+         if (!ifb->saw_error())
+           go_error_at(ifb->location(),
+                       ("import error for %qs: no else block "
+                        "for if statement at %lu"),
+                       ifb->name().c_str(),
+                       static_cast<unsigned long>(ifb->off()));
+         ifb->set_saw_error();
+         return Statement::make_error_statement(loc);
+       }
+
+      else_block = Block_statement::do_import(ifb, loc);
+      if (else_block == NULL)
+       return Statement::make_error_statement(loc);
+    }
+
+  return Statement::make_if_statement(cond, then_block, else_block, loc);
+}
+
 // Dump the AST representation for an if statement
 
 void
index 3743d44bb4362eeef7f8646c9779a1b3cc334050..3e85243b084febf0d0587de9e18e1adb6b5f50df 100644 (file)
@@ -954,6 +954,14 @@ class Block_statement : public Statement
   is_lowered_for_statement()
   { return this->is_lowered_for_statement_; }
 
+  // Export a block for a block statement.
+  static void
+  export_block(Export_function_body*, Block*);
+
+  // Import a block statement, returning the block.
+  static Block*
+  do_import(Import_function_body*, Location);
+
  protected:
   int
   do_traverse(Traverse* traverse)
@@ -1529,6 +1537,10 @@ class If_statement : public Statement
   else_block() const
   { return this->else_block_; }
 
+  // Import an if statement.
+  static Statement*
+  do_import(Import_function_body*, Location);
+
  protected:
   int
   do_traverse(Traverse*);
@@ -1539,6 +1551,13 @@ class If_statement : public Statement
   void
   do_check_types(Gogo*);
 
+  int
+  do_inlining_cost()
+  { return 5; }
+
+  void
+  do_export_statement(Export_function_body*);
+
   bool
   do_may_fall_through() const;