1
2
3
4
5
6
7 package interleaved
8
9 import (
10 "cmd/compile/internal/base"
11 "cmd/compile/internal/devirtualize"
12 "cmd/compile/internal/inline"
13 "cmd/compile/internal/inline/inlheur"
14 "cmd/compile/internal/ir"
15 "cmd/compile/internal/pgoir"
16 "cmd/compile/internal/typecheck"
17 "fmt"
18 )
19
20
21
22 func DevirtualizeAndInlinePackage(pkg *ir.Package, profile *pgoir.Profile) {
23 if profile != nil && base.Debug.PGODevirtualize > 0 {
24
25 ir.VisitFuncsBottomUp(typecheck.Target.Funcs, func(list []*ir.Func, recursive bool) {
26 for _, fn := range list {
27 devirtualize.ProfileGuided(fn, profile)
28 }
29 })
30 ir.CurFunc = nil
31 }
32
33 if base.Flag.LowerL != 0 {
34 inlheur.SetupScoreAdjustments()
35 }
36
37 var inlProfile *pgoir.Profile
38 if base.Debug.PGOInline != 0 {
39 inlProfile = profile
40 }
41
42
43 inline.CanInlineFuncs(pkg.Funcs, inlProfile)
44
45
46
47 for _, fn := range pkg.Funcs {
48 DevirtualizeAndInlineFunc(fn, inlProfile)
49 }
50
51 if base.Flag.LowerL != 0 {
52
53
54
55 inline.GarbageCollectUnreferencedHiddenClosures()
56
57 if base.Debug.DumpInlFuncProps != "" {
58 inlheur.DumpFuncProps(nil, base.Debug.DumpInlFuncProps)
59 }
60 if inlheur.Enabled() {
61 inline.PostProcessCallSites(inlProfile)
62 inlheur.TearDown()
63 }
64 }
65 }
66
67
68
69 func DevirtualizeAndInlineFunc(fn *ir.Func, profile *pgoir.Profile) {
70 ir.WithFunc(fn, func() {
71 if base.Flag.LowerL != 0 {
72 if inlheur.Enabled() && !fn.Wrapper() {
73 inlheur.ScoreCalls(fn)
74 defer inlheur.ScoreCallsCleanup()
75 }
76 if base.Debug.DumpInlFuncProps != "" && !fn.Wrapper() {
77 inlheur.DumpFuncProps(fn, base.Debug.DumpInlFuncProps)
78 }
79 }
80
81 bigCaller := base.Flag.LowerL != 0 && inline.IsBigFunc(fn)
82 if bigCaller && base.Flag.LowerM > 1 {
83 fmt.Printf("%v: function %v considered 'big'; reducing max cost of inlinees\n", ir.Line(fn), fn)
84 }
85
86 match := func(n ir.Node) bool {
87 switch n := n.(type) {
88 case *ir.CallExpr:
89 return true
90 case *ir.TailCallStmt:
91 n.Call.NoInline = true
92 }
93 return false
94 }
95
96 edit := func(n ir.Node) ir.Node {
97 call, ok := n.(*ir.CallExpr)
98 if !ok {
99 return nil
100 }
101
102 devirtualize.StaticCall(call)
103 if inlCall := inline.TryInlineCall(fn, call, bigCaller, profile); inlCall != nil {
104 return inlCall
105 }
106 return nil
107 }
108
109 fixpoint(fn, match, edit)
110 })
111 }
112
113
114
115
116
117
118
119
120
121
122
123 func fixpoint(fn *ir.Func, match func(ir.Node) bool, edit func(ir.Node) ir.Node) {
124
125
126
127
128
129
130
131
132
133
134 var parens []*ir.ParenExpr
135 var mark func(ir.Node) ir.Node
136 mark = func(n ir.Node) ir.Node {
137 if _, ok := n.(*ir.ParenExpr); ok {
138 return n
139 }
140
141 ok := match(n)
142
143 ir.EditChildren(n, mark)
144
145 if ok {
146 paren := ir.NewParenExpr(n.Pos(), n)
147 paren.SetType(n.Type())
148 paren.SetTypecheck(n.Typecheck())
149
150 parens = append(parens, paren)
151 n = paren
152 }
153
154 return n
155 }
156 ir.EditChildren(fn, mark)
157
158
159 for {
160 done := true
161
162 for i := 0; i < len(parens); i++ {
163 paren := parens[i]
164 if new := edit(paren.X); new != nil {
165
166 paren.X = new
167 ir.EditChildren(new, mark)
168 done = false
169 }
170 }
171
172 if done {
173 break
174 }
175 }
176
177
178 if len(parens) == 0 {
179 return
180 }
181 var unparen func(ir.Node) ir.Node
182 unparen = func(n ir.Node) ir.Node {
183 if paren, ok := n.(*ir.ParenExpr); ok {
184 n = paren.X
185 }
186 ir.EditChildren(n, unparen)
187 return n
188 }
189 ir.EditChildren(fn, unparen)
190 }
191
View as plain text