[dev.unified] cmd/compile/internal/noder: implicit conversions for multi-valued expressions

This CL changes GOEXPERIMENT=unified to insert implicit conversions
for multi-valued expressions.

Unfortunately, IR doesn't have strong, first-class support for
multi-valued expressions, so this CL takes the approach of spilling
them to temporary variables, which can then be implicitly converted.
This is the same approach taken by walk, but doing it this early does
introduce some minor complications:

1. For select case clauses with comma-ok assignments (e.g., `case x,
ok := <-ch:`), the compiler middle end wants to see the OAS2RECV
assignment is the CommClause.Comm statement. So when constructing
select statements, we need to massage this around a little.

2. The extra temporary variables and assignments skew the existing
inlining heuristics. As mentioned, the temporaries/assignments will
eventually be added (and often optimized away again) anyway, but now
they're visible to the inliner. So this CL also kludges the inlining
heuristics in this case to keep things comparable.

Change-Id: I3e3ea756ad92472ebe28bae3963be61ed7684a75
Reviewed-on: https://go-review.googlesource.com/c/go/+/415244
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Matthew Dempsky 2022-06-28 16:31:29 -07:00
parent e7219cc093
commit 3635b07d16
4 changed files with 97 additions and 9 deletions

View file

@ -430,6 +430,36 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
case ir.OMETHEXPR:
v.budget++ // Hack for toolstash -cmp.
case ir.OAS2:
n := n.(*ir.AssignListStmt)
// Unified IR unconditionally rewrites:
//
// a, b = f()
//
// into:
//
// DCL tmp1
// DCL tmp2
// tmp1, tmp2 = f()
// a, b = tmp1, tmp2
//
// so that it can insert implicit conversions as necessary. To
// minimize impact to the existing inlining heuristics (in
// particular, to avoid breaking the existing inlinability regress
// tests), we need to compensate for this here.
if base.Debug.Unified != 0 {
if init := n.Rhs[0].Init(); len(init) == 1 {
if _, ok := init[0].(*ir.AssignListStmt); ok {
// 4 for each value, because each temporary variable now
// appears 3 times (DCL, LHS, RHS), plus an extra DCL node.
//
// 1 for the extra "tmp1, tmp2 = f()" assignment statement.
v.budget += 4*int32(len(n.Lhs)) + 1
}
}
}
}
v.budget--