1
2
3
4
5 package ssacompile
6
7 import (
8 "fmt"
9 "testing"
10
11 "cmd/compile/internal/ssa"
12 "cmd/compile/internal/ssa/ssabase"
13 "cmd/compile/internal/ssa/ssaop"
14 "cmd/compile/internal/types"
15 "cmd/internal/obj/x86"
16 )
17
18 func TestLiveControlOps(t *testing.T) {
19 c := testConfig(t)
20 f := c.Fun("entry",
21 Bloc("entry",
22 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
23 Valu("x", ssaop.OpAMD64MOVLconst, c.config.Types.Int8, 1, nil),
24 Valu("y", ssaop.OpAMD64MOVLconst, c.config.Types.Int8, 2, nil),
25 Valu("a", ssaop.OpAMD64TESTB, types.TypeFlags, 0, nil, "x", "y"),
26 Valu("b", ssaop.OpAMD64TESTB, types.TypeFlags, 0, nil, "y", "x"),
27 Eq("a", "if", "exit"),
28 ),
29 Bloc("if",
30 Eq("b", "plain", "exit"),
31 ),
32 Bloc("plain",
33 Goto("exit"),
34 ),
35 Bloc("exit",
36 Exit("mem"),
37 ),
38 )
39 flagalloc(f.f)
40 regalloc(f.f)
41 checkFunc(f.f)
42 }
43
44
45
46 func TestNoGetgLoadReg(t *testing.T) {
47
57 c := testConfigARM64(t)
58 f := c.Fun("b1",
59 Bloc("b1",
60 Valu("v1", ssaop.OpInitMem, types.TypeMem, 0, nil),
61 Valu("v6", ssaop.OpArg, c.config.Types.Int64, 0, c.Temp(c.config.Types.Int64)),
62 Valu("v8", ssaop.OpGetG, c.config.Types.Int64.PtrTo(), 0, nil, "v1"),
63 Valu("v11", ssaop.OpARM64CMPconst, types.TypeFlags, 0, nil, "v6"),
64 Eq("v11", "b2", "b4"),
65 ),
66 Bloc("b4",
67 Goto("b3"),
68 ),
69 Bloc("b3",
70 Valu("v14", ssaop.OpPhi, types.TypeMem, 0, nil, "v1", "v12"),
71 Valu("sb", ssaop.OpSB, c.config.Types.Uintptr, 0, nil),
72 Valu("v16", ssaop.OpARM64MOVDstore, types.TypeMem, 0, nil, "v8", "sb", "v14"),
73 Exit("v16"),
74 ),
75 Bloc("b2",
76 Valu("v12", ssaop.OpARM64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "v1"),
77 Goto("b3"),
78 ),
79 )
80 regalloc(f.f)
81 checkFunc(f.f)
82
83 r := f.f.RegAlloc
84 for _, b := range f.blocks {
85 for _, v := range b.Values {
86 if v.Op == ssaop.OpLoadReg && r[v.ID].String() == "g" {
87 t.Errorf("Saw OpLoadReg targeting g register: %s", v.LongString())
88 }
89 }
90 }
91 }
92
93
94
95 func TestSpillWithLoop(t *testing.T) {
96 c := testConfig(t)
97 f := c.Fun("entry",
98 Bloc("entry",
99 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
100 Valu("ptr", ssaop.OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64)),
101 Valu("cond", ssaop.OpArg, c.config.Types.Bool, 0, c.Temp(c.config.Types.Bool)),
102 Valu("ld", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 0, nil, "ptr", "mem"),
103 Goto("loop"),
104 ),
105 Bloc("loop",
106 Valu("memphi", ssaop.OpPhi, types.TypeMem, 0, nil, "mem", "call"),
107 Valu("call", ssaop.OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "memphi"),
108 Valu("test", ssaop.OpAMD64CMPBconst, types.TypeFlags, 0, nil, "cond"),
109 Eq("test", "next", "exit"),
110 ),
111 Bloc("next",
112 Goto("loop"),
113 ),
114 Bloc("exit",
115 Valu("store", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "ptr", "ld", "call"),
116 Exit("store"),
117 ),
118 )
119 regalloc(f.f)
120 checkFunc(f.f)
121 for _, v := range f.blocks["loop"].Values {
122 if v.Op == ssaop.OpStoreReg {
123 t.Errorf("spill inside loop %s", v.LongString())
124 }
125 }
126 }
127
128 func TestSpillMove1(t *testing.T) {
129 c := testConfig(t)
130 f := c.Fun("entry",
131 Bloc("entry",
132 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
133 Valu("x", ssaop.OpArg, c.config.Types.Int64, 0, c.Temp(c.config.Types.Int64)),
134 Valu("p", ssaop.OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo())),
135 Valu("a", ssaop.OpAMD64TESTQ, types.TypeFlags, 0, nil, "x", "x"),
136 Goto("loop1"),
137 ),
138 Bloc("loop1",
139 Valu("y", ssaop.OpAMD64MULQ, c.config.Types.Int64, 0, nil, "x", "x"),
140 Eq("a", "loop2", "exit1"),
141 ),
142 Bloc("loop2",
143 Eq("a", "loop1", "exit2"),
144 ),
145 Bloc("exit1",
146
147 Valu("mem2", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem"),
148 Valu("mem3", ssaop.OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem2"),
149 Exit("mem3"),
150 ),
151 Bloc("exit2",
152
153 Valu("mem4", ssaop.OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
154 Valu("mem5", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem4"),
155 Exit("mem5"),
156 ),
157 )
158 flagalloc(f.f)
159 regalloc(f.f)
160 checkFunc(f.f)
161
162 if numSpills(f.blocks["loop1"]) != 0 {
163 t.Errorf("spill present from loop1")
164 }
165 if numSpills(f.blocks["loop2"]) != 0 {
166 t.Errorf("spill present in loop2")
167 }
168 if numSpills(f.blocks["exit1"]) != 0 {
169 t.Errorf("spill present in exit1")
170 }
171 if numSpills(f.blocks["exit2"]) != 1 {
172 t.Errorf("spill missing in exit2")
173 }
174
175 }
176
177 func TestSpillMove2(t *testing.T) {
178 c := testConfig(t)
179 f := c.Fun("entry",
180 Bloc("entry",
181 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
182 Valu("x", ssaop.OpArg, c.config.Types.Int64, 0, c.Temp(c.config.Types.Int64)),
183 Valu("p", ssaop.OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo())),
184 Valu("a", ssaop.OpAMD64TESTQ, types.TypeFlags, 0, nil, "x", "x"),
185 Goto("loop1"),
186 ),
187 Bloc("loop1",
188 Valu("y", ssaop.OpAMD64MULQ, c.config.Types.Int64, 0, nil, "x", "x"),
189 Eq("a", "loop2", "exit1"),
190 ),
191 Bloc("loop2",
192 Eq("a", "loop1", "exit2"),
193 ),
194 Bloc("exit1",
195
196 Valu("mem2", ssaop.OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
197 Valu("mem3", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem2"),
198 Exit("mem3"),
199 ),
200 Bloc("exit2",
201
202 Valu("mem4", ssaop.OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
203 Valu("mem5", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem4"),
204 Exit("mem5"),
205 ),
206 )
207 flagalloc(f.f)
208 regalloc(f.f)
209 checkFunc(f.f)
210
211
212 if numSpills(f.blocks["loop1"]) != 1 {
213 t.Errorf("spill missing from loop1")
214 }
215 if numSpills(f.blocks["loop2"]) != 0 {
216 t.Errorf("spill present in loop2")
217 }
218 if numSpills(f.blocks["exit1"]) != 0 {
219 t.Errorf("spill present in exit1")
220 }
221 if numSpills(f.blocks["exit2"]) != 0 {
222 t.Errorf("spill present in exit2")
223 }
224
225 }
226
227 func TestClobbersArg0(t *testing.T) {
228 c := testConfig(t)
229 f := c.Fun("entry",
230 Bloc("entry",
231 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
232 Valu("ptr", ssaop.OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo())),
233 Valu("dst", ssaop.OpArg, c.config.Types.Int64.PtrTo().PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo().PtrTo())),
234 Valu("zero", ssaop.OpAMD64LoweredZeroLoop, types.TypeMem, 256, nil, "ptr", "mem"),
235 Valu("store", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "dst", "ptr", "zero"),
236 Exit("store")))
237 flagalloc(f.f)
238 regalloc(f.f)
239 checkFunc(f.f)
240
241
242 if n := numCopies(f.blocks["entry"]); n != 1 {
243 fmt.Printf("%s\n", f.f.String())
244 t.Errorf("got %d copies, want 1", n)
245 }
246 }
247
248 func TestClobbersArg1(t *testing.T) {
249 c := testConfig(t)
250 f := c.Fun("entry",
251 Bloc("entry",
252 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
253 Valu("src", ssaop.OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo())),
254 Valu("dst", ssaop.OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo())),
255 Valu("use1", ssaop.OpArg, c.config.Types.Int64.PtrTo().PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo().PtrTo())),
256 Valu("use2", ssaop.OpArg, c.config.Types.Int64.PtrTo().PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo().PtrTo())),
257 Valu("move", ssaop.OpAMD64LoweredMoveLoop, types.TypeMem, 256, nil, "dst", "src", "mem"),
258 Valu("store1", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "use1", "src", "move"),
259 Valu("store2", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "use2", "dst", "store1"),
260 Exit("store2")))
261 flagalloc(f.f)
262 regalloc(f.f)
263 checkFunc(f.f)
264
265
266 if n := numCopies(f.blocks["entry"]); n != 2 {
267 fmt.Printf("%s\n", f.f.String())
268 t.Errorf("got %d copies, want 2", n)
269 }
270 }
271
272 func TestNoRematerializeDeadConstant(t *testing.T) {
273 c := testConfigARM64(t)
274 f := c.Fun("b1",
275 Bloc("b1",
276 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
277 Valu("addr", ssaop.OpArg, c.config.Types.Int32.PtrTo(), 0, c.Temp(c.config.Types.Int32.PtrTo())),
278 Valu("const", ssaop.OpARM64MOVDconst, c.config.Types.Int32, -1, nil),
279 Valu("cmp", ssaop.OpARM64CMPconst, types.TypeFlags, 0, nil, "const"),
280 Goto("b2"),
281 ),
282 Bloc("b2",
283 Valu("phi_mem", ssaop.OpPhi, types.TypeMem, 0, nil, "mem", "callmem"),
284 Eq("cmp", "b6", "b3"),
285 ),
286 Bloc("b3",
287 Valu("call", ssaop.OpARM64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "phi_mem"),
288 Valu("callmem", ssaop.OpSelectN, types.TypeMem, 0, nil, "call"),
289 Eq("cmp", "b5", "b4"),
290 ),
291 Bloc("b4",
292 Goto("b2"),
293 ),
294 Bloc("b5",
295 Valu("user", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "addr", "const", "callmem"),
296 Exit("user"),
297 ),
298 Bloc("b6",
299 Exit("phi_mem"),
300 ),
301 )
302
303 regalloc(f.f)
304 checkFunc(f.f)
305
306
307 for _, v := range f.blocks["b4"].Values {
308 if v.Op == ssaop.OpARM64MOVDconst && v.AuxInt == -1 {
309 t.Errorf("constant -1 rematerialized in loop block b4: %s", v.LongString())
310 }
311 }
312 }
313
314 func numSpills(b *ssa.Block) int {
315 return numOps(b, ssaop.OpStoreReg)
316 }
317 func numCopies(b *ssa.Block) int {
318 return numOps(b, ssaop.OpCopy)
319 }
320 func numOps(b *ssa.Block, op ssaop.Op) int {
321 n := 0
322 for _, v := range b.Values {
323 if v.Op == op {
324 n++
325 }
326 }
327 return n
328 }
329
330 func TestRematerializeableRegCompatible(t *testing.T) {
331 c := testConfig(t)
332 f := c.Fun("entry",
333 Bloc("entry",
334 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
335 Valu("x", ssaop.OpAMD64MOVLconst, c.config.Types.Int32, 1, nil),
336 Valu("a", ssaop.OpAMD64POR, c.config.Types.Float32, 0, nil, "x", "x"),
337 Valu("res", ssaop.OpMakeResult, types.NewResults([]*types.Type{c.config.Types.Float32, types.TypeMem}), 0, nil, "a", "mem"),
338 Ret("res"),
339 ),
340 )
341 regalloc(f.f)
342 checkFunc(f.f)
343 moveFound := false
344 for _, v := range f.f.Blocks[0].Values {
345 if v.Op == ssaop.OpCopy && x86.REG_X0 <= v.Reg() && v.Reg() <= x86.REG_X31 {
346 moveFound = true
347 }
348 }
349 if !moveFound {
350 t.Errorf("Expects an Copy to be issued, but got: %+v", f.f)
351 }
352 }
353
354 func TestPreload(t *testing.T) {
355 c := testConfig(t)
356
357
358 f := c.Fun("entry",
359 Bloc("entry",
360 Valu("ptr", ssaop.OpArgIntReg, c.config.Types.Int8.PtrTo(), 0, &ssa.AuxNameOffset{Name: c.Temp(c.config.Types.Int8.PtrTo()), Offset: 0}),
361 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
362 Valu("x0", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 0, nil, "ptr", "mem"),
363 Valu("x1", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 1, nil, "ptr", "mem"),
364 Valu("x2", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 2, nil, "ptr", "mem"),
365 Valu("x3", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 3, nil, "ptr", "mem"),
366 Valu("x4", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 4, nil, "ptr", "mem"),
367 Valu("x5", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 5, nil, "ptr", "mem"),
368 Valu("x6", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 6, nil, "ptr", "mem"),
369 Valu("x7", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 7, nil, "ptr", "mem"),
370 Valu("x8", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 8, nil, "ptr", "mem"),
371 Valu("x9", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 9, nil, "ptr", "mem"),
372 Valu("x10", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 10, nil, "ptr", "mem"),
373 Valu("x11", ssaop.OpAMD64MOVBload, c.config.Types.Int8, 11, nil, "ptr", "mem"),
374 Valu("init", ssaop.OpAMD64MOVQconst, c.config.Types.Int64, 0, nil),
375 Goto("loopHead"),
376 ),
377 Bloc("loopHead",
378 Valu("phi", ssaop.OpPhi, c.config.Types.Int64, 0, nil, "init", "next"),
379 Valu("test", ssaop.OpAMD64CMPQconst, types.TypeFlags, 10, nil, "phi"),
380 Lt("test", "loopBody", "exit"),
381 ),
382 Bloc("loopBody",
383 Valu("next", ssaop.OpAMD64ADDQconst, c.config.Types.Int64, 1, nil, "phi"),
384 Goto("loopHead"),
385 ),
386 Bloc("exit",
387 Valu("m0", ssaop.OpAMD64MOVBstore, types.TypeMem, 0, nil, "ptr", "x0", "mem"),
388 Valu("m1", ssaop.OpAMD64MOVBstore, types.TypeMem, 1, nil, "ptr", "x1", "m0"),
389 Valu("m2", ssaop.OpAMD64MOVBstore, types.TypeMem, 2, nil, "ptr", "x2", "m1"),
390 Valu("m3", ssaop.OpAMD64MOVBstore, types.TypeMem, 3, nil, "ptr", "x3", "m2"),
391 Valu("m4", ssaop.OpAMD64MOVBstore, types.TypeMem, 4, nil, "ptr", "x4", "m3"),
392 Valu("m5", ssaop.OpAMD64MOVBstore, types.TypeMem, 5, nil, "ptr", "x5", "m4"),
393 Valu("m6", ssaop.OpAMD64MOVBstore, types.TypeMem, 6, nil, "ptr", "x6", "m5"),
394 Valu("m7", ssaop.OpAMD64MOVBstore, types.TypeMem, 7, nil, "ptr", "x7", "m6"),
395 Valu("m8", ssaop.OpAMD64MOVBstore, types.TypeMem, 8, nil, "ptr", "x8", "m7"),
396 Valu("m9", ssaop.OpAMD64MOVBstore, types.TypeMem, 9, nil, "ptr", "x9", "m8"),
397 Valu("m10", ssaop.OpAMD64MOVBstore, types.TypeMem, 10, nil, "ptr", "x10", "m9"),
398 Valu("m11", ssaop.OpAMD64MOVBstore, types.TypeMem, 11, nil, "ptr", "x11", "m10"),
399 Ret("m11"),
400 ),
401 )
402 f.f.Blocks[1].Likely = ssa.BranchLikely
403 regalloc(f.f)
404 checkFunc(f.f)
405
406 v := f.values["phi"]
407 loc := f.f.RegAlloc[v.ID]
408 if _, ok := loc.(*ssabase.Register); !ok {
409 t.Errorf("Expects to use a register for phi, but got: %s\n%v", loc, f.f)
410 }
411 }
412
413
414
415
416
417
418 func TestStartRegsDrop(t *testing.T) {
419 c := testConfig(t)
420
421 f := c.Fun("entry",
422 Bloc("entry",
423 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
424 Valu("ptr", ssaop.OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64)),
425
426 Valu("u0", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 100, nil, "ptr", "mem"),
427 Valu("u1", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 108, nil, "ptr", "mem"),
428 Valu("u2", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 116, nil, "ptr", "mem"),
429 Valu("u3", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 124, nil, "ptr", "mem"),
430 Valu("u4", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 132, nil, "ptr", "mem"),
431 Valu("u5", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 140, nil, "ptr", "mem"),
432 Valu("u6", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 148, nil, "ptr", "mem"),
433 Valu("u7", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 156, nil, "ptr", "mem"),
434
435 Valu("v0", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 0, nil, "ptr", "mem"),
436
437 Valu("cond", ssaop.OpAMD64MOVLconst, c.config.Types.Int32, 1, nil),
438 Valu("test", ssaop.OpAMD64TESTL, types.TypeFlags, 0, nil, "cond", "cond"),
439 Eq("test", "left", "right"),
440 ),
441 Bloc("left",
442
443
444 Goto("merge"),
445 ),
446 Bloc("right",
447
448
449 Valu("r0", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 200, nil, "ptr", "mem"),
450 Valu("r1", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 208, nil, "ptr", "mem"),
451 Valu("r2", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 216, nil, "ptr", "mem"),
452 Valu("r3", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 224, nil, "ptr", "mem"),
453 Valu("r4", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 232, nil, "ptr", "mem"),
454 Valu("r5", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 240, nil, "ptr", "mem"),
455 Valu("r6", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 248, nil, "ptr", "mem"),
456 Valu("r7", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 256, nil, "ptr", "mem"),
457 Valu("r8", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 264, nil, "ptr", "mem"),
458 Valu("r9", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 272, nil, "ptr", "mem"),
459 Valu("r10", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 280, nil, "ptr", "mem"),
460 Valu("r11", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 288, nil, "ptr", "mem"),
461 Valu("r12", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 296, nil, "ptr", "mem"),
462 Valu("r13", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 304, nil, "ptr", "mem"),
463 Valu("r14", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 312, nil, "ptr", "mem"),
464 Valu("r15", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 320, nil, "ptr", "mem"),
465 Valu("sum0", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "r0", "r1"),
466 Valu("sum1", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "r2", "r3"),
467 Valu("sum2", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "r4", "r5"),
468 Valu("sum3", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "r6", "r7"),
469 Valu("sum4", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "r8", "r9"),
470 Valu("sum5", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "r10", "r11"),
471 Valu("sum6", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "r12", "r13"),
472 Valu("sum7", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "r14", "r15"),
473 Valu("store0", ssaop.OpAMD64MOVQstore, types.TypeMem, 400, nil, "ptr", "sum0", "mem"),
474 Valu("store1", ssaop.OpAMD64MOVQstore, types.TypeMem, 408, nil, "ptr", "sum1", "store0"),
475 Valu("store2", ssaop.OpAMD64MOVQstore, types.TypeMem, 416, nil, "ptr", "sum2", "store1"),
476 Valu("store3", ssaop.OpAMD64MOVQstore, types.TypeMem, 424, nil, "ptr", "sum3", "store2"),
477 Valu("store4", ssaop.OpAMD64MOVQstore, types.TypeMem, 432, nil, "ptr", "sum4", "store3"),
478 Valu("store5", ssaop.OpAMD64MOVQstore, types.TypeMem, 440, nil, "ptr", "sum5", "store4"),
479 Valu("store6", ssaop.OpAMD64MOVQstore, types.TypeMem, 448, nil, "ptr", "sum6", "store5"),
480 Valu("store7", ssaop.OpAMD64MOVQstore, types.TypeMem, 456, nil, "ptr", "sum7", "store6"),
481 Goto("merge"),
482 ),
483 Bloc("merge",
484
485 Valu("p0", ssaop.OpPhi, c.config.Types.Int64, 0, nil, "v0", "v0"),
486
487 Valu("n0", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 500, nil, "ptr", "mem"),
488 Valu("n1", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 508, nil, "ptr", "mem"),
489 Valu("n2", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 516, nil, "ptr", "mem"),
490 Valu("n3", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 524, nil, "ptr", "mem"),
491 Valu("n4", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 532, nil, "ptr", "mem"),
492 Valu("n5", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 540, nil, "ptr", "mem"),
493 Valu("n6", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 548, nil, "ptr", "mem"),
494 Valu("n7", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 556, nil, "ptr", "mem"),
495 Valu("n8", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 564, nil, "ptr", "mem"),
496 Valu("n9", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 572, nil, "ptr", "mem"),
497 Valu("n10", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 580, nil, "ptr", "mem"),
498 Valu("n11", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 588, nil, "ptr", "mem"),
499 Valu("n12", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 596, nil, "ptr", "mem"),
500 Valu("n13", ssaop.OpAMD64MOVQload, c.config.Types.Int64, 604, nil, "ptr", "mem"),
501
502 Valu("a0", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "n0", "n1"),
503 Valu("a1", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "n2", "n3"),
504 Valu("a2", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "n4", "n5"),
505 Valu("a3", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "n6", "n7"),
506 Valu("a4", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "n8", "n9"),
507 Valu("a5", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "n10", "n11"),
508 Valu("a6", ssaop.OpAMD64ADDQ, c.config.Types.Int64, 0, nil, "n12", "n13"),
509 Valu("s0", ssaop.OpAMD64MOVQstore, types.TypeMem, 0, nil, "ptr", "a0", "mem"),
510 Valu("s1", ssaop.OpAMD64MOVQstore, types.TypeMem, 8, nil, "ptr", "a1", "s0"),
511 Valu("s2", ssaop.OpAMD64MOVQstore, types.TypeMem, 16, nil, "ptr", "a2", "s1"),
512 Valu("s3", ssaop.OpAMD64MOVQstore, types.TypeMem, 24, nil, "ptr", "a3", "s2"),
513 Valu("s4", ssaop.OpAMD64MOVQstore, types.TypeMem, 32, nil, "ptr", "a4", "s3"),
514 Valu("s5", ssaop.OpAMD64MOVQstore, types.TypeMem, 40, nil, "ptr", "a5", "s4"),
515 Valu("s6", ssaop.OpAMD64MOVQstore, types.TypeMem, 48, nil, "ptr", "a6", "s5"),
516
517 Valu("t0", ssaop.OpAMD64MOVQstore, types.TypeMem, 100, nil, "ptr", "u0", "s6"),
518 Valu("t1", ssaop.OpAMD64MOVQstore, types.TypeMem, 108, nil, "ptr", "u1", "t0"),
519 Valu("t2", ssaop.OpAMD64MOVQstore, types.TypeMem, 116, nil, "ptr", "u2", "t1"),
520 Valu("t3", ssaop.OpAMD64MOVQstore, types.TypeMem, 124, nil, "ptr", "u3", "t2"),
521 Valu("t4", ssaop.OpAMD64MOVQstore, types.TypeMem, 132, nil, "ptr", "u4", "t3"),
522 Valu("t5", ssaop.OpAMD64MOVQstore, types.TypeMem, 140, nil, "ptr", "u5", "t4"),
523 Valu("t6", ssaop.OpAMD64MOVQstore, types.TypeMem, 148, nil, "ptr", "u6", "t5"),
524 Valu("t7", ssaop.OpAMD64MOVQstore, types.TypeMem, 156, nil, "ptr", "u7", "t6"),
525 Exit("t7"),
526 ),
527 )
528
529 regalloc(f.f)
530 checkFunc(f.f)
531
532 leftLoadCount := numOps(f.blocks["left"], ssaop.OpLoadReg)
533 rightLoadCount := numOps(f.blocks["right"], ssaop.OpLoadReg)
534 t.Logf("OpLoadReg count in left: %d, right: %d", leftLoadCount, rightLoadCount)
535
536
537 if rightLoadCount > 8 {
538 t.Errorf("expected <= 8 OpLoadReg in right block (got %d)", rightLoadCount)
539 }
540 }
541
View as plain text