compiler: intrinsify sync/atomic functions
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 30 May 2019 17:26:46 +0000 (17:26 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 30 May 2019 17:26:46 +0000 (17:26 +0000)
    Let the Go frontend recognize sync/atomic functions and turn them
    into intrinsics.

    Also make sure not to intrinsify calls in go or defer statements.

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

From-SVN: r271784

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/statements.cc

index 6a291b5402a83fc4b72a974da3ac928e3e324a8b..b7b0f5027b830a400011628f39b5b73a332d6556 100644 (file)
@@ -1,4 +1,4 @@
-84b8000c32f671c6cc89df1290ed6e0170308644
+4dc60d989293d070702024e7dea52b9849f74775
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index ad898b7f38c8b591e8e7c22766bf3bd226aa8a67..e3a662736a0907794bd2c3a7f533e19f23bb2341 100644 (file)
@@ -10432,7 +10432,8 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
 
   // Lower to compiler intrinsic if possible.
   Func_expression* fe = this->fn_->func_expression();
-  if (fe != NULL
+  if (!this->is_concurrent_ && !this->is_deferred_
+      && fe != NULL
       && (fe->named_object()->is_function_declaration()
           || fe->named_object()->is_function()))
     {
@@ -10471,6 +10472,73 @@ Call_expression::intrinsify(Gogo* gogo,
   int int_size = int_type->named_type()->real_type()->integer_type()->bits() / 8;
   int ptr_size = uintptr_type->named_type()->real_type()->integer_type()->bits() / 8;
 
+  if (package == "sync/atomic")
+    {
+      // sync/atomic functions and runtime/internal/atomic functions
+      // are very similar. In order not to duplicate code, we just
+      // redirect to the latter and let the code below to handle them.
+      // In case there is no equivalent functions (slight variance
+      // in types), we just make an artificial name (begin with '$').
+      // Note: no StorePointer, SwapPointer, and CompareAndSwapPointer,
+      // as they need write barriers.
+      if (name == "LoadInt32")
+        name = "$Loadint32";
+      else if (name == "LoadInt64")
+        name = "Loadint64";
+      else if (name == "LoadUint32")
+        name = "Load";
+      else if (name == "LoadUint64")
+        name = "Load64";
+      else if (name == "LoadUintptr")
+        name = "Loaduintptr";
+      else if (name == "LoadPointer")
+        name = "Loadp";
+      else if (name == "StoreInt32")
+        name = "$Storeint32";
+      else if (name == "StoreInt64")
+        name = "$Storeint64";
+      else if (name == "StoreUint32")
+        name = "Store";
+      else if (name == "StoreUint64")
+        name = "Store64";
+      else if (name == "StoreUintptr")
+        name = "Storeuintptr";
+      else if (name == "AddInt32")
+        name = "$Xaddint32";
+      else if (name == "AddInt64")
+        name = "Xaddint64";
+      else if (name == "AddUint32")
+        name = "Xadd";
+      else if (name == "AddUint64")
+        name = "Xadd64";
+      else if (name == "AddUintptr")
+        name = "Xadduintptr";
+      else if (name == "SwapInt32")
+        name = "$Xchgint32";
+      else if (name == "SwapInt64")
+        name = "$Xchgint64";
+      else if (name == "SwapUint32")
+        name = "Xchg";
+      else if (name == "SwapUint64")
+        name = "Xchg64";
+      else if (name == "SwapUintptr")
+        name = "Xchguintptr";
+      else if (name == "CompareAndSwapInt32")
+        name = "$Casint32";
+      else if (name == "CompareAndSwapInt64")
+        name = "$Casint64";
+      else if (name == "CompareAndSwapUint32")
+        name = "Cas";
+      else if (name == "CompareAndSwapUint64")
+        name = "Cas64";
+      else if (name == "CompareAndSwapUintptr")
+        name = "Casuintptr";
+      else
+        return NULL;
+
+      package = "runtime/internal/atomic";
+    }
+
   if (package == "runtime")
     {
       // Handle a couple of special runtime functions.  In the runtime
@@ -10557,7 +10625,8 @@ Call_expression::intrinsify(Gogo* gogo,
       int memorder = __ATOMIC_SEQ_CST;
 
       if ((name == "Load" || name == "Load64" || name == "Loadint64" || name == "Loadp"
-           || name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq")
+           || name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq"
+           || name == "$Loadint32")
           && this->args_ != NULL && this->args_->size() == 1)
         {
           if (int_size < 8 && (name == "Load64" || name == "Loadint64"))
@@ -10577,6 +10646,11 @@ Call_expression::intrinsify(Gogo* gogo,
               code = Runtime::ATOMIC_LOAD_8;
               res_type = uint64_type;
             }
+          else if (name == "$Loadint32")
+            {
+              code = Runtime::ATOMIC_LOAD_4;
+              res_type = int32_type;
+            }
           else if (name == "Loadint64")
             {
               code = Runtime::ATOMIC_LOAD_8;
@@ -10618,10 +10692,11 @@ Call_expression::intrinsify(Gogo* gogo,
         }
 
       if ((name == "Store" || name == "Store64" || name == "StorepNoWB"
-           || name == "Storeuintptr" || name == "StoreRel")
+           || name == "Storeuintptr" || name == "StoreRel"
+           || name == "$Storeint32" || name == "$Storeint64")
           && this->args_ != NULL && this->args_->size() == 2)
         {
-          if (int_size < 8 && name == "Store64")
+          if (int_size < 8 && (name == "Store64" || name == "$Storeint64"))
             return NULL;
 
           Runtime::Function code;
@@ -10631,6 +10706,10 @@ Call_expression::intrinsify(Gogo* gogo,
             code = Runtime::ATOMIC_STORE_4;
           else if (name == "Store64")
             code = Runtime::ATOMIC_STORE_8;
+          else if (name == "$Storeint32")
+            code = Runtime::ATOMIC_STORE_4;
+          else if (name == "$Storeint64")
+            code = Runtime::ATOMIC_STORE_8;
           else if (name == "Storeuintptr")
             code = (ptr_size == 8 ? Runtime::ATOMIC_STORE_8 : Runtime::ATOMIC_STORE_4);
           else if (name == "StorepNoWB")
@@ -10650,10 +10729,11 @@ Call_expression::intrinsify(Gogo* gogo,
           return Runtime::make_call(code, loc, 3, a1, a2, a3);
         }
 
-      if ((name == "Xchg" || name == "Xchg64" || name == "Xchguintptr")
+      if ((name == "Xchg" || name == "Xchg64" || name == "Xchguintptr"
+           || name == "$Xchgint32" || name == "$Xchgint64")
           && this->args_ != NULL && this->args_->size() == 2)
         {
-          if (int_size < 8 && name == "Xchg64")
+          if (int_size < 8 && (name == "Xchg64" || name == "Xchgint64"))
             return NULL;
 
           Runtime::Function code;
@@ -10668,6 +10748,16 @@ Call_expression::intrinsify(Gogo* gogo,
               code = Runtime::ATOMIC_EXCHANGE_8;
               res_type = uint64_type;
             }
+          else if (name == "$Xchgint32")
+            {
+              code = Runtime::ATOMIC_EXCHANGE_4;
+              res_type = int32_type;
+            }
+          else if (name == "$Xchgint64")
+            {
+              code = Runtime::ATOMIC_EXCHANGE_8;
+              res_type = int64_type;
+            }
           else if (name == "Xchguintptr")
             {
               code = (ptr_size == 8
@@ -10685,10 +10775,11 @@ Call_expression::intrinsify(Gogo* gogo,
         }
 
       if ((name == "Cas" || name == "Cas64" || name == "Casuintptr"
-           || name == "Casp1" || name == "CasRel")
+           || name == "Casp1" || name == "CasRel"
+           || name == "$Casint32" || name == "$Casint64")
           && this->args_ != NULL && this->args_->size() == 3)
         {
-          if (int_size < 8 && name == "Cas64")
+          if (int_size < 8 && (name == "Cas64" || name == "$Casint64"))
             return NULL;
 
           Runtime::Function code;
@@ -10707,6 +10798,10 @@ Call_expression::intrinsify(Gogo* gogo,
             code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
           else if (name == "Cas64")
             code = Runtime::ATOMIC_COMPARE_EXCHANGE_8;
+          else if (name == "$Casint32")
+            code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
+          else if (name == "$Casint64")
+            code = Runtime::ATOMIC_COMPARE_EXCHANGE_8;
           else if (name == "Casuintptr")
             code = (ptr_size == 8
                     ? Runtime::ATOMIC_COMPARE_EXCHANGE_8
@@ -10733,7 +10828,7 @@ Call_expression::intrinsify(Gogo* gogo,
         }
 
       if ((name == "Xadd" || name == "Xadd64" || name == "Xaddint64"
-           || name == "Xadduintptr")
+           || name == "Xadduintptr" || name == "$Xaddint32")
           && this->args_ != NULL && this->args_->size() == 2)
         {
           if (int_size < 8 && (name == "Xadd64" || name == "Xaddint64"))
@@ -10751,6 +10846,11 @@ Call_expression::intrinsify(Gogo* gogo,
               code = Runtime::ATOMIC_ADD_FETCH_8;
               res_type = uint64_type;
             }
+          else if (name == "$Xaddint32")
+            {
+              code = Runtime::ATOMIC_ADD_FETCH_4;
+              res_type = int32_type;
+            }
           else if (name == "Xaddint64")
             {
               code = Runtime::ATOMIC_ADD_FETCH_8;
index c850b49bebd564c8e1ad5700a2ffadc88a6b3ee2..e3354892b40015e93308fa515307bcd47dc98842 100644 (file)
@@ -2682,8 +2682,6 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
 
   gogo->add_conversions_in_block(b);
 
-  gogo->flatten_block(function, b);
-
   if (may_call_recover
       || recover_arg != NULL
       || this->classification() == STATEMENT_GO)
@@ -2707,6 +2705,8 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
        }
     }
 
+  gogo->flatten_block(function, b);
+
   // That is all the thunk has to do.
   gogo->finish_function(location);
 }