Skip to content

Commit cced777

Browse files
committed
cmd/compile: set n.Name.Defn for inlined parameters
Normally, when variables are declared and initialized using ":=", we set the variable's n.Name.Defn to point to the initialization assignment node (i.e., OAS or OAS2). Further, some frontend optimizations look for variables that are initialized but never reassigned. However, when inl.go inlines calls, it was declaring the inlined variables, and then separately assigning to them. This CL changes inl.go tweaks the AST to fit the combined declaration+initialization pattern. This isn't terribly useful by itself, but it allows further followup optimizations. Updates #41474. Change-Id: I62a9752c60414305679e0ed15a6563baa0224efa Reviewed-on: https://go-review.googlesource.com/c/go/+/256457 Run-TryBot: Matthew Dempsky <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Matthew Dempsky <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]>
1 parent 8773d14 commit cced777

File tree

2 files changed

+33
-43
lines changed

2 files changed

+33
-43
lines changed

src/cmd/compile/internal/gc/inl.go

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -831,16 +831,19 @@ func (v *reassignVisitor) visitList(l Nodes) *Node {
831831
return nil
832832
}
833833

834-
func tinlvar(t *types.Field, inlvars map[*Node]*Node) *Node {
835-
if n := asNode(t.Nname); n != nil && !n.isBlank() {
836-
inlvar := inlvars[n]
837-
if inlvar == nil {
838-
Fatalf("missing inlvar for %v\n", n)
839-
}
840-
return inlvar
834+
func inlParam(t *types.Field, as *Node, inlvars map[*Node]*Node) *Node {
835+
n := asNode(t.Nname)
836+
if n == nil || n.isBlank() {
837+
return nblank
841838
}
842839

843-
return typecheck(nblank, ctxExpr|ctxAssign)
840+
inlvar := inlvars[n]
841+
if inlvar == nil {
842+
Fatalf("missing inlvar for %v", n)
843+
}
844+
as.Ninit.Append(nod(ODCL, inlvar, nil))
845+
inlvar.Name.Defn = as
846+
return inlvar
844847
}
845848

846849
var inlgen int
@@ -970,14 +973,15 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
970973
continue
971974
}
972975
if ln.isParamStackCopy() { // ignore the on-stack copy of a parameter that moved to the heap
973-
continue
974-
}
975-
inlvars[ln] = typecheck(inlvar(ln), ctxExpr)
976-
if ln.Class() == PPARAM || ln.Name.Param.Stackcopy != nil && ln.Name.Param.Stackcopy.Class() == PPARAM {
977-
ninit.Append(nod(ODCL, inlvars[ln], nil))
976+
// TODO(mdempsky): Remove once I'm confident
977+
// this never actually happens. We currently
978+
// perform inlining before escape analysis, so
979+
// nothing should have moved to the heap yet.
980+
Fatalf("impossible: %v", ln)
978981
}
982+
inlf := typecheck(inlvar(ln), ctxExpr)
983+
inlvars[ln] = inlf
979984
if genDwarfInline > 0 {
980-
inlf := inlvars[ln]
981985
if ln.Class() == PPARAM {
982986
inlf.Name.SetInlFormal(true)
983987
} else {
@@ -1019,56 +1023,42 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
10191023

10201024
// Assign arguments to the parameters' temp names.
10211025
as := nod(OAS2, nil, nil)
1022-
as.Rlist.Set(n.List.Slice())
1026+
as.SetColas(true)
1027+
if n.Op == OCALLMETH {
1028+
if n.Left.Left == nil {
1029+
Fatalf("method call without receiver: %+v", n)
1030+
}
1031+
as.Rlist.Append(n.Left.Left)
1032+
}
1033+
as.Rlist.Append(n.List.Slice()...)
10231034

10241035
// For non-dotted calls to variadic functions, we assign the
10251036
// variadic parameter's temp name separately.
10261037
var vas *Node
10271038

1028-
if fn.IsMethod() {
1029-
rcv := fn.Type.Recv()
1030-
1031-
if n.Left.Op == ODOTMETH {
1032-
// For x.M(...), assign x directly to the
1033-
// receiver parameter.
1034-
if n.Left.Left == nil {
1035-
Fatalf("method call without receiver: %+v", n)
1036-
}
1037-
ras := nod(OAS, tinlvar(rcv, inlvars), n.Left.Left)
1038-
ras = typecheck(ras, ctxStmt)
1039-
ninit.Append(ras)
1040-
} else {
1041-
// For T.M(...), add the receiver parameter to
1042-
// as.List, so it's assigned by the normal
1043-
// arguments.
1044-
if as.Rlist.Len() == 0 {
1045-
Fatalf("non-method call to method without first arg: %+v", n)
1046-
}
1047-
as.List.Append(tinlvar(rcv, inlvars))
1048-
}
1039+
if recv := fn.Type.Recv(); recv != nil {
1040+
as.List.Append(inlParam(recv, as, inlvars))
10491041
}
1050-
10511042
for _, param := range fn.Type.Params().Fields().Slice() {
10521043
// For ordinary parameters or variadic parameters in
10531044
// dotted calls, just add the variable to the
10541045
// assignment list, and we're done.
10551046
if !param.IsDDD() || n.IsDDD() {
1056-
as.List.Append(tinlvar(param, inlvars))
1047+
as.List.Append(inlParam(param, as, inlvars))
10571048
continue
10581049
}
10591050

10601051
// Otherwise, we need to collect the remaining values
10611052
// to pass as a slice.
10621053

1063-
numvals := n.List.Len()
1064-
10651054
x := as.List.Len()
1066-
for as.List.Len() < numvals {
1055+
for as.List.Len() < as.Rlist.Len() {
10671056
as.List.Append(argvar(param.Type, as.List.Len()))
10681057
}
10691058
varargs := as.List.Slice()[x:]
10701059

1071-
vas = nod(OAS, tinlvar(param, inlvars), nil)
1060+
vas = nod(OAS, nil, nil)
1061+
vas.Left = inlParam(param, vas, inlvars)
10721062
if len(varargs) == 0 {
10731063
vas.Right = nodnil()
10741064
vas.Right.Type = param.Type

src/cmd/compile/internal/logopt/logopt_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ func s15a8(x *[15]int64) [15]int64 {
213213
want(t, slogged, `{"range":{"start":{"line":7,"character":13},"end":{"line":7,"character":13}},"severity":3,"code":"leak","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0",`+
214214
`"relatedInformation":[`+
215215
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: y = z:"},`+
216-
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y = \u003cN\u003e (assign-pair)"},`+
216+
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y := z (assign-pair)"},`+
217217
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: ~r1 = y:"},`+
218218
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+
219219
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y.b (dot of pointer)"},`+

0 commit comments

Comments
 (0)