Commit c9c41a6b by Ian Lance Taylor

compiler: intrinsify sync/atomic functions

    
    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
parent d05b516e
84b8000c32f671c6cc89df1290ed6e0170308644 4dc60d989293d070702024e7dea52b9849f74775
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -10432,7 +10432,8 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*, ...@@ -10432,7 +10432,8 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
// Lower to compiler intrinsic if possible. // Lower to compiler intrinsic if possible.
Func_expression* fe = this->fn_->func_expression(); 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_declaration()
|| fe->named_object()->is_function())) || fe->named_object()->is_function()))
{ {
...@@ -10471,6 +10472,73 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10471,6 +10472,73 @@ Call_expression::intrinsify(Gogo* gogo,
int int_size = int_type->named_type()->real_type()->integer_type()->bits() / 8; 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; 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") if (package == "runtime")
{ {
// Handle a couple of special runtime functions. In the runtime // Handle a couple of special runtime functions. In the runtime
...@@ -10557,7 +10625,8 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10557,7 +10625,8 @@ Call_expression::intrinsify(Gogo* gogo,
int memorder = __ATOMIC_SEQ_CST; int memorder = __ATOMIC_SEQ_CST;
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")
&& 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"))
...@@ -10577,6 +10646,11 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10577,6 +10646,11 @@ Call_expression::intrinsify(Gogo* gogo,
code = Runtime::ATOMIC_LOAD_8; code = Runtime::ATOMIC_LOAD_8;
res_type = uint64_type; res_type = uint64_type;
} }
else if (name == "$Loadint32")
{
code = Runtime::ATOMIC_LOAD_4;
res_type = int32_type;
}
else if (name == "Loadint64") else if (name == "Loadint64")
{ {
code = Runtime::ATOMIC_LOAD_8; code = Runtime::ATOMIC_LOAD_8;
...@@ -10618,10 +10692,11 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10618,10 +10692,11 @@ Call_expression::intrinsify(Gogo* gogo,
} }
if ((name == "Store" || name == "Store64" || name == "StorepNoWB" 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) && this->args_ != NULL && this->args_->size() == 2)
{ {
if (int_size < 8 && name == "Store64") if (int_size < 8 && (name == "Store64" || name == "$Storeint64"))
return NULL; return NULL;
Runtime::Function code; Runtime::Function code;
...@@ -10631,6 +10706,10 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10631,6 +10706,10 @@ Call_expression::intrinsify(Gogo* gogo,
code = Runtime::ATOMIC_STORE_4; code = Runtime::ATOMIC_STORE_4;
else if (name == "Store64") else if (name == "Store64")
code = Runtime::ATOMIC_STORE_8; 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") else if (name == "Storeuintptr")
code = (ptr_size == 8 ? Runtime::ATOMIC_STORE_8 : Runtime::ATOMIC_STORE_4); code = (ptr_size == 8 ? Runtime::ATOMIC_STORE_8 : Runtime::ATOMIC_STORE_4);
else if (name == "StorepNoWB") else if (name == "StorepNoWB")
...@@ -10650,10 +10729,11 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10650,10 +10729,11 @@ Call_expression::intrinsify(Gogo* gogo,
return Runtime::make_call(code, loc, 3, a1, a2, a3); 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) && this->args_ != NULL && this->args_->size() == 2)
{ {
if (int_size < 8 && name == "Xchg64") if (int_size < 8 && (name == "Xchg64" || name == "Xchgint64"))
return NULL; return NULL;
Runtime::Function code; Runtime::Function code;
...@@ -10668,6 +10748,16 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10668,6 +10748,16 @@ Call_expression::intrinsify(Gogo* gogo,
code = Runtime::ATOMIC_EXCHANGE_8; code = Runtime::ATOMIC_EXCHANGE_8;
res_type = uint64_type; 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") else if (name == "Xchguintptr")
{ {
code = (ptr_size == 8 code = (ptr_size == 8
...@@ -10685,10 +10775,11 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10685,10 +10775,11 @@ Call_expression::intrinsify(Gogo* gogo,
} }
if ((name == "Cas" || name == "Cas64" || name == "Casuintptr" 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) && this->args_ != NULL && this->args_->size() == 3)
{ {
if (int_size < 8 && name == "Cas64") if (int_size < 8 && (name == "Cas64" || name == "$Casint64"))
return NULL; return NULL;
Runtime::Function code; Runtime::Function code;
...@@ -10707,6 +10798,10 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10707,6 +10798,10 @@ Call_expression::intrinsify(Gogo* gogo,
code = Runtime::ATOMIC_COMPARE_EXCHANGE_4; code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
else if (name == "Cas64") else if (name == "Cas64")
code = Runtime::ATOMIC_COMPARE_EXCHANGE_8; 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") else if (name == "Casuintptr")
code = (ptr_size == 8 code = (ptr_size == 8
? Runtime::ATOMIC_COMPARE_EXCHANGE_8 ? Runtime::ATOMIC_COMPARE_EXCHANGE_8
...@@ -10733,7 +10828,7 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10733,7 +10828,7 @@ Call_expression::intrinsify(Gogo* gogo,
} }
if ((name == "Xadd" || name == "Xadd64" || name == "Xaddint64" if ((name == "Xadd" || name == "Xadd64" || name == "Xaddint64"
|| name == "Xadduintptr") || name == "Xadduintptr" || name == "$Xaddint32")
&& this->args_ != NULL && this->args_->size() == 2) && this->args_ != NULL && this->args_->size() == 2)
{ {
if (int_size < 8 && (name == "Xadd64" || name == "Xaddint64")) if (int_size < 8 && (name == "Xadd64" || name == "Xaddint64"))
...@@ -10751,6 +10846,11 @@ Call_expression::intrinsify(Gogo* gogo, ...@@ -10751,6 +10846,11 @@ Call_expression::intrinsify(Gogo* gogo,
code = Runtime::ATOMIC_ADD_FETCH_8; code = Runtime::ATOMIC_ADD_FETCH_8;
res_type = uint64_type; res_type = uint64_type;
} }
else if (name == "$Xaddint32")
{
code = Runtime::ATOMIC_ADD_FETCH_4;
res_type = int32_type;
}
else if (name == "Xaddint64") else if (name == "Xaddint64")
{ {
code = Runtime::ATOMIC_ADD_FETCH_8; code = Runtime::ATOMIC_ADD_FETCH_8;
......
...@@ -2682,8 +2682,6 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name) ...@@ -2682,8 +2682,6 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
gogo->add_conversions_in_block(b); gogo->add_conversions_in_block(b);
gogo->flatten_block(function, b);
if (may_call_recover if (may_call_recover
|| recover_arg != NULL || recover_arg != NULL
|| this->classification() == STATEMENT_GO) || this->classification() == STATEMENT_GO)
...@@ -2707,6 +2705,8 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name) ...@@ -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. // That is all the thunk has to do.
gogo->finish_function(location); gogo->finish_function(location);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment