This patch to the Go frontend reduces the number of temporaries that the compiler genrrates for composite literals. 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 (GCC PR 101064). This is for that PR and for https://golang.org/issue/46600. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline and GCC 11 branch.
Ian
98df89168805cd34409307ef0495721d69acef74 diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index f16fb9facc3..f7bcc8c484a 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -bcafcb3c39530bb325514d6377747eb3127d1a03 +cad187fe3aceb2a7d964b64c70dfa8c8ad24ce65 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 5d45e4baab4..94342b2f9b8 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -15148,7 +15148,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*, @@ -15162,10 +15162,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()) @@ -15173,7 +15176,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); @@ -15448,7 +15452,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*, @@ -15467,6 +15471,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();