diff mbox series

Go patch committed: Support inlining functions with if statements

Message ID CAOyqgcUW4xRQRFPYAoO+wCRpgvuX6LqUKdUKE4C9HvU7VLy1ow@mail.gmail.com
State New
Headers show
Series Go patch committed: Support inlining functions with if statements | expand

Commit Message

Ian Lance Taylor June 7, 2019, 2:20 p.m. UTC
This patch to the Go frontend supports inlining functions with if
statements.  This increases the number of inlinable functions from 455
to 500.  An example of a newly inlinable function is strings.Compare.
Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 272043)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 272043)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -6941,7 +6941,12 @@  Block::import_block(Block* set, Import_f
 
       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: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 272022)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -129,22 +129,8 @@  Statement::import_statement(Import_funct
 {
   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_funct
     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(" = ");
@@ -2121,13 +2109,19 @@  Statement::make_statement(Expression* ex
 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(Exp
   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_c
 					  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: gcc/go/gofrontend/statements.h
===================================================================
--- gcc/go/gofrontend/statements.h	(revision 272043)
+++ gcc/go/gofrontend/statements.h	(working copy)
@@ -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;