diff mbox series

Go patch committed: Recognize Go 1.18 runtime/internal/atomic methods

Message ID CAOyqgcXN6gqUDGe11=DCnSyCrWjXSV39X+Nk2NodzKn_Wkc-bA@mail.gmail.com
State New
Headers show
Series Go patch committed: Recognize Go 1.18 runtime/internal/atomic methods | expand

Commit Message

Ian Lance Taylor Feb. 9, 2022, 4:14 a.m. UTC
The Go 1.18 library introduces specific types in
runtime/internal/atomic.  This patch to the Go frontend recognizes and
optimizes the methods on those types, as we do with the functions in
runtime/internal/atomic.

While we're here avoid getting confused by methods in any other
package that we recognize specially.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian

* go-gcc.cc (Gcc_backend::Gcc_backend): Define builtins
__atomic_load_1 and __atomic_store_1.

pa
869fb813039e8933a85f5f2a3a53cde156030b0a
diff mbox series

Patch

diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 631996073f4..f3de7a8c183 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -897,6 +897,20 @@  Gcc_backend::Gcc_backend()
   this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", NULL,
                        t, 0);
 
+  t = build_function_type_list(unsigned_char_type_node,
+			       ptr_type_node,
+			       integer_type_node,
+			       NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1", NULL, t, 0);
+
+  t = build_function_type_list(void_type_node,
+			       ptr_type_node,
+			       unsigned_char_type_node,
+			       integer_type_node,
+			       NULL_TREE);
+  this->define_builtin(BUILT_IN_ATOMIC_STORE_1, "__atomic_store_1", NULL,
+		       t, 0);
+
   t = build_function_type_list(unsigned_char_type_node,
                                ptr_type_node,
                                unsigned_char_type_node,
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 5f4adf9d0e7..9cd22ef011e 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@ 
-262cb89fd5ed82ab135a3933b2ddf4eb67683149
+3b1e46937d11b043d0986a3dfefaee27454c3da0
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 1e6890a3cc5..d7b64767a00 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -11613,12 +11613,16 @@  Call_expression::intrinsify(Gogo* gogo,
   std::string package = (no->package() != NULL
                          ? no->package()->pkgpath()
                          : gogo->pkgpath());
+  bool is_method = ((no->is_function() && no->func_value()->is_method())
+		    || (no->is_function_declaration()
+			&& no->func_declaration_value()->is_method()));
   Location loc = this->location();
 
   Type* int_type = Type::lookup_integer_type("int");
   Type* int32_type = Type::lookup_integer_type("int32");
   Type* int64_type = Type::lookup_integer_type("int64");
   Type* uint_type = Type::lookup_integer_type("uint");
+  Type* uint8_type = Type::lookup_integer_type("uint8");
   Type* uint32_type = Type::lookup_integer_type("uint32");
   Type* uint64_type = Type::lookup_integer_type("uint64");
   Type* uintptr_type = Type::lookup_integer_type("uintptr");
@@ -11629,6 +11633,9 @@  Call_expression::intrinsify(Gogo* gogo,
 
   if (package == "sync/atomic")
     {
+      if (is_method)
+	return NULL;
+
       // 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.
@@ -11694,6 +11701,9 @@  Call_expression::intrinsify(Gogo* gogo,
 
   if (package == "runtime/internal/sys")
     {
+      if (is_method)
+	return NULL;
+
       // runtime/internal/sys functions and math/bits functions
       // are very similar. In order not to duplicate code, we just
       // redirect to the latter and let the code below to handle them.
@@ -11713,6 +11723,9 @@  Call_expression::intrinsify(Gogo* gogo,
 
   if (package == "runtime")
     {
+      if (is_method)
+	return NULL;
+
       // Handle a couple of special runtime functions.  In the runtime
       // package, getcallerpc returns the PC of the caller, and
       // getcallersp returns the frame pointer of the caller.  Implement
@@ -11743,6 +11756,9 @@  Call_expression::intrinsify(Gogo* gogo,
     }
   else if (package == "math/bits")
     {
+      if (is_method)
+	return NULL;
+
       if ((name == "ReverseBytes16" || name == "ReverseBytes32"
            || name == "ReverseBytes64" || name == "ReverseBytes")
           && this->args_ != NULL && this->args_->size() == 1)
@@ -11913,9 +11929,137 @@  Call_expression::intrinsify(Gogo* gogo,
     {
       int memorder = __ATOMIC_SEQ_CST;
 
+      if (is_method)
+	{
+	  Function_type* ftype = (no->is_function()
+				  ? no->func_value()->type()
+				  : no->func_declaration_value()->type());
+	  Type* rtype = ftype->receiver()->type()->deref();
+	  go_assert(rtype->named_type() != NULL);
+	  const std::string& rname(rtype->named_type()->name());
+	  if (rname == "Int32")
+	    {
+	      if (name == "Load")
+		name = "LoadInt32";
+	      else if (name == "Store")
+		name = "Storeint32";
+	      else if (name == "CompareAndSwap")
+		name = "Casint32";
+	      else if (name == "Swap")
+		name = "Xchgint32";
+	      else if (name == "Add")
+		name = "Xaddint32";
+	      else
+		go_unreachable();
+	    }
+	  else if (rname == "Int64")
+	    {
+	      if (name == "Load")
+		name = "LoadInt64";
+	      else if (name == "Store")
+		name = "Storeint64";
+	      else if (name == "CompareAndSwap")
+		name = "Casint64";
+	      else if (name == "Swap")
+		name = "Xchgint64";
+	      else if (name == "Add")
+		name = "Xaddint64";
+	      else
+		go_unreachable();
+	    }
+	  else if (rname == "Uint8")
+	    {
+	      if (name == "Load")
+		name = "Load8";
+	      else if (name == "Store")
+		name = "Store8";
+	      else if (name == "And")
+		name = "And8";
+	      else if (name == "Or")
+		name = "Or8";
+	      else
+		go_unreachable();
+	    }
+	  else if (rname == "Uint32")
+	    {
+	      if (name == "Load")
+		name = "Load";
+	      else if (name == "LoadAcquire")
+		name = "LoadAcq";
+	      else if (name == "Store")
+		name = "Store";
+	      else if (name == "CompareAndSwap")
+		name = "Cas";
+	      else if (name == "CompareAndSwapRelease")
+		name = "CasRel";
+	      else if (name == "Swap")
+		name = "Xchg";
+	      else if (name == "And")
+		name = "And";
+	      else if (name == "Or")
+		name = "Or";
+	      else if (name == "Add")
+		name = "Xadd";
+	      else
+		go_unreachable();
+	    }
+	  else if (rname == "Uint64")
+	    {
+	      if (name == "Load")
+		name = "Load64";
+	      else if (name == "Store")
+		name = "Store64";
+	      else if (name == "CompareAndSwap")
+		name = "Cas64";
+	      else if (name == "Swap")
+		name = "Xchgt64";
+	      else if (name == "Add")
+		name = "Xadd64";
+	      else
+		go_unreachable();
+	    }
+	  else if (rname == "Uintptr")
+	    {
+	      if (name == "Load")
+		name = "Loaduintptr";
+	      else if (name == "LoadAcquire")
+		name = "Loadacquintptr";
+	      else if (name == "Store")
+		name = "Storeuintptr";
+	      else if (name == "StoreRelease")
+		name = "StoreReluintptr";
+	      else if (name == "CompareAndSwap")
+		name = "Casuintptr";
+	      else if (name == "Swap")
+		name = "Xchguintptr";
+	      else if (name == "Add")
+		name = "Xadduintptr";
+	      else
+		go_unreachable();
+	    }
+	  else if (rname == "Float64")
+	    {
+	      // Needs unsafe type conversion.  Don't intrinsify for now.
+	      return NULL;
+	    }
+	  else if (rname == "UnsafePointer")
+	    {
+	      if (name == "Load")
+		name = "Loadp";
+	      else if (name == "StoreNoWB")
+		name = "StorepoWB";
+	      else if (name == "CompareAndSwapNoWB")
+		name = "Casp1";
+	      else
+		go_unreachable();
+	    }
+	  else
+	    go_unreachable();
+	}
+
       if ((name == "Load" || name == "Load64" || name == "Loadint64" || name == "Loadp"
            || name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq"
-           || name == "Loadint32")
+           || name == "Loadint32" || name == "Load8")
           && this->args_ != NULL && this->args_->size() == 1)
         {
           if (int_size < 8 && (name == "Load64" || name == "Loadint64"))
@@ -11972,6 +12116,11 @@  Call_expression::intrinsify(Gogo* gogo,
               res_type = uint32_type;
               memorder = __ATOMIC_ACQUIRE;
             }
+	  else if (name == "Load8")
+	    {
+	      code = Runtime::ATOMIC_LOAD_1;
+	      res_type = uint8_type;
+	    }
           else
             go_unreachable();
           Expression* a1 = this->args_->front();
@@ -12012,6 +12161,8 @@  Call_expression::intrinsify(Gogo* gogo,
               code = Runtime::ATOMIC_STORE_4;
               memorder = __ATOMIC_RELEASE;
             }
+	  else if (name == "Store8")
+	    code = Runtime::ATOMIC_STORE_1;
           else
             go_unreachable();
           Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
@@ -12179,6 +12330,9 @@  Call_expression::intrinsify(Gogo* gogo,
     }
   else if (package == "internal/abi")
     {
+      if (is_method)
+	return NULL;
+
       if ((name == "FuncPCABI0" || name == "FuncPCABIInternal")
 	  && this->args_ != NULL
 	  && this->args_->size() == 1)
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 87a27085d60..b7dd4456a25 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -478,6 +478,10 @@  DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4",
 DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
                P3(POINTER, UINT64, INT32),
                R1(UINT64))
+DEF_GO_RUNTIME(ATOMIC_LOAD_1, "__atomic_load_1", P2(POINTER, INT32),
+	       R1(UINT8))
+DEF_GO_RUNTIME(ATOMIC_STORE_1, "__atomic_store_1", P3(POINTER, UINT8, INT32),
+	       R0())
 DEF_GO_RUNTIME(ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
                P3(POINTER, UINT8, INT32),
                R1(UINT8))