compiler: recognize Go 1.18 runtime/internal/atomic methods

The Go 1.18 library introduces specific types in runtime/internal/atomic.
Recognize and optimize 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.

Change-Id: I75c31f75dcf65ce13f3c69022e8ec36e05eab994
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/383654
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Ian Lance Taylor 2022-02-06 18:25:25 -08:00
Родитель 262cb89fd5
Коммит 3b1e46937d
2 изменённых файлов: 159 добавлений и 1 удалений

Просмотреть файл

@ -11613,12 +11613,16 @@ Call_expression::intrinsify(Gogo* gogo,
std::string package = (no->package() != NULL std::string package = (no->package() != NULL
? no->package()->pkgpath() ? no->package()->pkgpath()
: gogo->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(); Location loc = this->location();
Type* int_type = Type::lookup_integer_type("int"); Type* int_type = Type::lookup_integer_type("int");
Type* int32_type = Type::lookup_integer_type("int32"); Type* int32_type = Type::lookup_integer_type("int32");
Type* int64_type = Type::lookup_integer_type("int64"); Type* int64_type = Type::lookup_integer_type("int64");
Type* uint_type = Type::lookup_integer_type("uint"); 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* uint32_type = Type::lookup_integer_type("uint32");
Type* uint64_type = Type::lookup_integer_type("uint64"); Type* uint64_type = Type::lookup_integer_type("uint64");
Type* uintptr_type = Type::lookup_integer_type("uintptr"); Type* uintptr_type = Type::lookup_integer_type("uintptr");
@ -11629,6 +11633,9 @@ Call_expression::intrinsify(Gogo* gogo,
if (package == "sync/atomic") if (package == "sync/atomic")
{ {
if (is_method)
return NULL;
// sync/atomic functions and runtime/internal/atomic functions // sync/atomic functions and runtime/internal/atomic functions
// are very similar. In order not to duplicate code, we just // are very similar. In order not to duplicate code, we just
// redirect to the latter and let the code below to handle them. // 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 (package == "runtime/internal/sys")
{ {
if (is_method)
return NULL;
// runtime/internal/sys functions and math/bits functions // runtime/internal/sys functions and math/bits functions
// are very similar. In order not to duplicate code, we just // are very similar. In order not to duplicate code, we just
// redirect to the latter and let the code below to handle them. // 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 (package == "runtime")
{ {
if (is_method)
return NULL;
// Handle a couple of special runtime functions. In the runtime // Handle a couple of special runtime functions. In the runtime
// package, getcallerpc returns the PC of the caller, and // package, getcallerpc returns the PC of the caller, and
// getcallersp returns the frame pointer of the caller. Implement // getcallersp returns the frame pointer of the caller. Implement
@ -11743,6 +11756,9 @@ Call_expression::intrinsify(Gogo* gogo,
} }
else if (package == "math/bits") else if (package == "math/bits")
{ {
if (is_method)
return NULL;
if ((name == "ReverseBytes16" || name == "ReverseBytes32" if ((name == "ReverseBytes16" || name == "ReverseBytes32"
|| name == "ReverseBytes64" || name == "ReverseBytes") || name == "ReverseBytes64" || name == "ReverseBytes")
&& this->args_ != NULL && this->args_->size() == 1) && this->args_ != NULL && this->args_->size() == 1)
@ -11913,9 +11929,137 @@ Call_expression::intrinsify(Gogo* gogo,
{ {
int memorder = __ATOMIC_SEQ_CST; 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" if ((name == "Load" || name == "Load64" || name == "Loadint64" || name == "Loadp"
|| name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq" || name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq"
|| name == "Loadint32") || name == "Loadint32" || name == "Load8")
&& this->args_ != NULL && this->args_->size() == 1) && this->args_ != NULL && this->args_->size() == 1)
{ {
if (int_size < 8 && (name == "Load64" || name == "Loadint64")) if (int_size < 8 && (name == "Load64" || name == "Loadint64"))
@ -11972,6 +12116,11 @@ Call_expression::intrinsify(Gogo* gogo,
res_type = uint32_type; res_type = uint32_type;
memorder = __ATOMIC_ACQUIRE; memorder = __ATOMIC_ACQUIRE;
} }
else if (name == "Load8")
{
code = Runtime::ATOMIC_LOAD_1;
res_type = uint8_type;
}
else else
go_unreachable(); go_unreachable();
Expression* a1 = this->args_->front(); Expression* a1 = this->args_->front();
@ -12012,6 +12161,8 @@ Call_expression::intrinsify(Gogo* gogo,
code = Runtime::ATOMIC_STORE_4; code = Runtime::ATOMIC_STORE_4;
memorder = __ATOMIC_RELEASE; memorder = __ATOMIC_RELEASE;
} }
else if (name == "Store8")
code = Runtime::ATOMIC_STORE_1;
else else
go_unreachable(); go_unreachable();
Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc); Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
@ -12179,6 +12330,9 @@ Call_expression::intrinsify(Gogo* gogo,
} }
else if (package == "internal/abi") else if (package == "internal/abi")
{ {
if (is_method)
return NULL;
if ((name == "FuncPCABI0" || name == "FuncPCABIInternal") if ((name == "FuncPCABI0" || name == "FuncPCABIInternal")
&& this->args_ != NULL && this->args_ != NULL
&& this->args_->size() == 1) && this->args_->size() == 1)

Просмотреть файл

@ -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", DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
P3(POINTER, UINT64, INT32), P3(POINTER, UINT64, INT32),
R1(UINT64)) 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", DEF_GO_RUNTIME(ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
P3(POINTER, UINT8, INT32), P3(POINTER, UINT8, INT32),
R1(UINT8)) R1(UINT8))