compiler: in composite literals use temps only for interfaces
For a composite literal we only need to introduce a temporary variable if we may be converting to an interface type, so only do it then. This saves over 80% of compilation time when using gccgo to compile cmd/internal/obj/x86, as the GCC middle-end spends a lot of time pointlessly computing interactions between temporary variables. For PR debug/101064 For golang/go#46600 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/331513
This commit is contained in:
parent
2cf8d3fc05
commit
528ed79401
@ -15141,7 +15141,7 @@ Struct_construction_expression::do_copy()
|
||||
}
|
||||
|
||||
// Flatten a struct construction expression. Store the values into
|
||||
// temporaries in case they need interface conversion.
|
||||
// temporaries if they may need interface conversion.
|
||||
|
||||
Expression*
|
||||
Struct_construction_expression::do_flatten(Gogo*, Named_object*,
|
||||
@ -15155,10 +15155,13 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*,
|
||||
return this;
|
||||
|
||||
Location loc = this->location();
|
||||
const Struct_field_list* fields = this->type_->struct_type()->fields();
|
||||
Struct_field_list::const_iterator pf = fields->begin();
|
||||
for (Expression_list::iterator pv = this->vals()->begin();
|
||||
pv != this->vals()->end();
|
||||
++pv)
|
||||
++pv, ++pf)
|
||||
{
|
||||
go_assert(pf != fields->end());
|
||||
if (*pv != NULL)
|
||||
{
|
||||
if ((*pv)->is_error_expression() || (*pv)->type()->is_error_type())
|
||||
@ -15166,7 +15169,8 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*,
|
||||
go_assert(saw_errors());
|
||||
return Expression::make_error(loc);
|
||||
}
|
||||
if (!(*pv)->is_multi_eval_safe())
|
||||
if (pf->type()->interface_type() != NULL
|
||||
&& !(*pv)->is_multi_eval_safe())
|
||||
{
|
||||
Temporary_statement* temp =
|
||||
Statement::make_temporary(NULL, *pv, loc);
|
||||
@ -15441,7 +15445,7 @@ Array_construction_expression::do_check_types(Gogo*)
|
||||
}
|
||||
|
||||
// Flatten an array construction expression. Store the values into
|
||||
// temporaries in case they need interface conversion.
|
||||
// temporaries if they may need interface conversion.
|
||||
|
||||
Expression*
|
||||
Array_construction_expression::do_flatten(Gogo*, Named_object*,
|
||||
@ -15460,6 +15464,11 @@ Array_construction_expression::do_flatten(Gogo*, Named_object*,
|
||||
if (this->is_constant_array() || this->is_static_initializer())
|
||||
return this;
|
||||
|
||||
// If the array element type is not an interface type, we don't need
|
||||
// temporaries.
|
||||
if (this->type_->array_type()->element_type()->interface_type() == NULL)
|
||||
return this;
|
||||
|
||||
Location loc = this->location();
|
||||
for (Expression_list::iterator pv = this->vals()->begin();
|
||||
pv != this->vals()->end();
|
||||
|
Loading…
Reference in New Issue
Block a user