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
merge done from the gofrontend repository.
......@@ -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;
......
......@@ -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);
}
......
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