1
2
3
4
5 package ssa
6
7 import (
8 "cmd/compile/internal/types"
9 "cmd/internal/src"
10 "testing"
11 )
12
13 func TestLiveControlOps(t *testing.T) {
14 c := testConfig(t)
15 f := c.Fun("entry",
16 Bloc("entry",
17 Valu("mem", OpInitMem, types.TypeMem, 0, nil),
18 Valu("x", OpAMD64MOVLconst, c.config.Types.Int8, 1, nil),
19 Valu("y", OpAMD64MOVLconst, c.config.Types.Int8, 2, nil),
20 Valu("a", OpAMD64TESTB, types.TypeFlags, 0, nil, "x", "y"),
21 Valu("b", OpAMD64TESTB, types.TypeFlags, 0, nil, "y", "x"),
22 Eq("a", "if", "exit"),
23 ),
24 Bloc("if",
25 Eq("b", "plain", "exit"),
26 ),
27 Bloc("plain",
28 Goto("exit"),
29 ),
30 Bloc("exit",
31 Exit("mem"),
32 ),
33 )
34 flagalloc(f.f)
35 regalloc(f.f)
36 checkFunc(f.f)
37 }
38
39
40
41 func TestNoGetgLoadReg(t *testing.T) {
42
52 c := testConfigARM64(t)
53 f := c.Fun("b1",
54 Bloc("b1",
55 Valu("v1", OpInitMem, types.TypeMem, 0, nil),
56 Valu("v6", OpArg, c.config.Types.Int64, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)),
57 Valu("v8", OpGetG, c.config.Types.Int64.PtrTo(), 0, nil, "v1"),
58 Valu("v11", OpARM64CMPconst, types.TypeFlags, 0, nil, "v6"),
59 Eq("v11", "b2", "b4"),
60 ),
61 Bloc("b4",
62 Goto("b3"),
63 ),
64 Bloc("b3",
65 Valu("v14", OpPhi, types.TypeMem, 0, nil, "v1", "v12"),
66 Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
67 Valu("v16", OpARM64MOVDstore, types.TypeMem, 0, nil, "v8", "sb", "v14"),
68 Exit("v16"),
69 ),
70 Bloc("b2",
71 Valu("v12", OpARM64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "v1"),
72 Goto("b3"),
73 ),
74 )
75 regalloc(f.f)
76 checkFunc(f.f)
77
78 r := f.f.RegAlloc
79 for _, b := range f.blocks {
80 for _, v := range b.Values {
81 if v.Op == OpLoadReg && r[v.ID].String() == "g" {
82 t.Errorf("Saw OpLoadReg targeting g register: %s", v.LongString())
83 }
84 }
85 }
86 }
87
88
89
90 func TestSpillWithLoop(t *testing.T) {
91 c := testConfig(t)
92 f := c.Fun("entry",
93 Bloc("entry",
94 Valu("mem", OpInitMem, types.TypeMem, 0, nil),
95 Valu("ptr", OpArg, c.config.Types.Int64.PtrTo(), 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)),
96 Valu("cond", OpArg, c.config.Types.Bool, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Bool)),
97 Valu("ld", OpAMD64MOVQload, c.config.Types.Int64, 0, nil, "ptr", "mem"),
98 Goto("loop"),
99 ),
100 Bloc("loop",
101 Valu("memphi", OpPhi, types.TypeMem, 0, nil, "mem", "call"),
102 Valu("call", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "memphi"),
103 Valu("test", OpAMD64CMPBconst, types.TypeFlags, 0, nil, "cond"),
104 Eq("test", "next", "exit"),
105 ),
106 Bloc("next",
107 Goto("loop"),
108 ),
109 Bloc("exit",
110 Valu("store", OpAMD64MOVQstore, types.TypeMem, 0, nil, "ptr", "ld", "call"),
111 Exit("store"),
112 ),
113 )
114 regalloc(f.f)
115 checkFunc(f.f)
116 for _, v := range f.blocks["loop"].Values {
117 if v.Op == OpStoreReg {
118 t.Errorf("spill inside loop %s", v.LongString())
119 }
120 }
121 }
122
123 func TestSpillMove1(t *testing.T) {
124 c := testConfig(t)
125 f := c.Fun("entry",
126 Bloc("entry",
127 Valu("mem", OpInitMem, types.TypeMem, 0, nil),
128 Valu("x", OpArg, c.config.Types.Int64, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)),
129 Valu("p", OpArg, c.config.Types.Int64.PtrTo(), 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64.PtrTo())),
130 Valu("a", OpAMD64TESTQ, types.TypeFlags, 0, nil, "x", "x"),
131 Goto("loop1"),
132 ),
133 Bloc("loop1",
134 Valu("y", OpAMD64MULQ, c.config.Types.Int64, 0, nil, "x", "x"),
135 Eq("a", "loop2", "exit1"),
136 ),
137 Bloc("loop2",
138 Eq("a", "loop1", "exit2"),
139 ),
140 Bloc("exit1",
141
142 Valu("mem2", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem"),
143 Valu("mem3", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem2"),
144 Exit("mem3"),
145 ),
146 Bloc("exit2",
147
148 Valu("mem4", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
149 Valu("mem5", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem4"),
150 Exit("mem5"),
151 ),
152 )
153 flagalloc(f.f)
154 regalloc(f.f)
155 checkFunc(f.f)
156
157 if numSpills(f.blocks["loop1"]) != 0 {
158 t.Errorf("spill present from loop1")
159 }
160 if numSpills(f.blocks["loop2"]) != 0 {
161 t.Errorf("spill present in loop2")
162 }
163 if numSpills(f.blocks["exit1"]) != 0 {
164 t.Errorf("spill present in exit1")
165 }
166 if numSpills(f.blocks["exit2"]) != 1 {
167 t.Errorf("spill missing in exit2")
168 }
169
170 }
171
172 func TestSpillMove2(t *testing.T) {
173 c := testConfig(t)
174 f := c.Fun("entry",
175 Bloc("entry",
176 Valu("mem", OpInitMem, types.TypeMem, 0, nil),
177 Valu("x", OpArg, c.config.Types.Int64, 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64)),
178 Valu("p", OpArg, c.config.Types.Int64.PtrTo(), 0, c.Frontend().Auto(src.NoXPos, c.config.Types.Int64.PtrTo())),
179 Valu("a", OpAMD64TESTQ, types.TypeFlags, 0, nil, "x", "x"),
180 Goto("loop1"),
181 ),
182 Bloc("loop1",
183 Valu("y", OpAMD64MULQ, c.config.Types.Int64, 0, nil, "x", "x"),
184 Eq("a", "loop2", "exit1"),
185 ),
186 Bloc("loop2",
187 Eq("a", "loop1", "exit2"),
188 ),
189 Bloc("exit1",
190
191 Valu("mem2", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
192 Valu("mem3", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem2"),
193 Exit("mem3"),
194 ),
195 Bloc("exit2",
196
197 Valu("mem4", OpAMD64CALLstatic, types.TypeMem, 0, AuxCallLSym("_"), "mem"),
198 Valu("mem5", OpAMD64MOVQstore, types.TypeMem, 0, nil, "p", "y", "mem4"),
199 Exit("mem5"),
200 ),
201 )
202 flagalloc(f.f)
203 regalloc(f.f)
204 checkFunc(f.f)
205
206
207 if numSpills(f.blocks["loop1"]) != 1 {
208 t.Errorf("spill missing from loop1")
209 }
210 if numSpills(f.blocks["loop2"]) != 0 {
211 t.Errorf("spill present in loop2")
212 }
213 if numSpills(f.blocks["exit1"]) != 0 {
214 t.Errorf("spill present in exit1")
215 }
216 if numSpills(f.blocks["exit2"]) != 0 {
217 t.Errorf("spill present in exit2")
218 }
219
220 }
221
222 func numSpills(b *Block) int {
223 n := 0
224 for _, v := range b.Values {
225 if v.Op == OpStoreReg {
226 n++
227 }
228 }
229 return n
230 }
231
View as plain text