1
2
3
4
5 package ssacompile
6
7 import (
8 "math"
9 "math/rand"
10 "reflect"
11 "testing"
12 "unsafe"
13
14 "cmd/compile/internal/rttype"
15 "cmd/compile/internal/ssa"
16 )
17
18
19
20 func TestMove(t *testing.T) {
21 x := [...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}
22 copy(x[1:], x[:])
23 for i := 1; i < len(x); i++ {
24 if int(x[i]) != i {
25 t.Errorf("Memmove got converted to OpMove in alias-unsafe way. Got %d instead of %d in position %d", int(x[i]), i, i+1)
26 }
27 }
28 }
29
30 func TestMoveSmall(t *testing.T) {
31 x := [...]byte{1, 2, 3, 4, 5, 6, 7}
32 copy(x[1:], x[:])
33 for i := 1; i < len(x); i++ {
34 if int(x[i]) != i {
35 t.Errorf("Memmove got converted to OpMove in alias-unsafe way. Got %d instead of %d in position %d", int(x[i]), i, i+1)
36 }
37 }
38 }
39
40 func TestSubFlags(t *testing.T) {
41 if !ssa.SubFlags32(0, 1).Lt() {
42 t.Errorf("subFlags32(0,1).lt() returned false")
43 }
44 if !ssa.SubFlags32(0, 1).Ult() {
45 t.Errorf("subFlags32(0,1).ult() returned false")
46 }
47 }
48
49
50 func unopt(f func(float64) float64, x float32) float32 {
51 return float32(f(float64(x)))
52 }
53
54 func differ(x, y float32) bool {
55 if x != x && y != y {
56
57 return false
58 }
59 return math.Float32bits(x) != math.Float32bits(y)
60 }
61
62 func test32bitUnary(t *testing.T, x float32) {
63 if want, got := unopt(math.Round, x), float32(math.Round(float64(x))); differ(want, got) {
64 t.Errorf("Optimized 32-bit Round did not match, x=%f, want=%f, got=%f", x, want, got)
65 }
66 if want, got := unopt(math.RoundToEven, x), float32(math.RoundToEven(float64(x))); differ(want, got) {
67 t.Errorf("Optimized 32-bit RoundToEven did not match, x=%f, want=%f, got=%f", x, want, got)
68 }
69 if want, got := unopt(math.Trunc, x), float32(math.Trunc(float64(x))); differ(want, got) {
70 t.Errorf("Optimized 32-bit Trunc did not match, x=%f, want=%f, got=%f", x, want, got)
71 }
72 if want, got := unopt(math.Ceil, x), float32(math.Ceil(float64(x))); differ(want, got) {
73 t.Errorf("Optimized 32-bit Ceil did not match, x=%f, want=%f, got=%f", x, want, got)
74 }
75 if want, got := unopt(math.Floor, x), float32(math.Floor(float64(x))); differ(want, got) {
76 t.Errorf("Optimized 32-bit Floor did not match, x=%f, want=%f, got=%f", x, want, got)
77 }
78 if x >= 0 {
79 if want, got := unopt(math.Sqrt, x), float32(math.Sqrt(float64(x))); differ(want, got) {
80 t.Errorf("Optimized 32-bit Sqrt did not match, x=%f, want=%f, got=%f", x, want, got)
81 }
82 }
83 if want, got := unopt(math.Abs, x), float32(math.Abs(float64(x))); differ(want, got) {
84 t.Errorf("Optimized 32-bit Abs did not match, x=%f, want=%f, got=%f", x, want, got)
85 }
86
87 }
88
89 var zero float32
90
91 func Test32bitUnary(t *testing.T) {
92
93 test32bitUnary(t, -1.5)
94 test32bitUnary(t, -0.5)
95 test32bitUnary(t, 0.5)
96 test32bitUnary(t, 1.5)
97
98 test32bitUnary(t, -1.4)
99 test32bitUnary(t, -0.4)
100 test32bitUnary(t, 0.4)
101 test32bitUnary(t, 1.4)
102
103 test32bitUnary(t, -1.6)
104 test32bitUnary(t, -0.6)
105 test32bitUnary(t, 0.6)
106 test32bitUnary(t, 1.6)
107
108
109 test32bitUnary(t, 1/(-1/zero))
110
111 var rnd = rand.New(rand.NewSource(0))
112
113 for i := uint32(0); i <= 1<<20; i++ {
114 test32bitUnary(t, math.Float32frombits(math.Float32bits(math.MaxFloat32)-i))
115 test32bitUnary(t, float32(i)+1.5)
116 test32bitUnary(t, math.Float32frombits(rnd.Uint32()))
117 }
118
119 }
120
121 func TestIsPPC64WordRotateMask(t *testing.T) {
122 tests := []struct {
123 input int64
124 expected bool
125 }{
126 {0x00000001, true},
127 {0x80000001, true},
128 {0x80010001, false},
129 {0xFFFFFFFA, false},
130 {0xF0F0F0F0, false},
131 {0xFFFFFFFD, true},
132 {0x80000000, true},
133 {0x00000000, false},
134 {0xFFFFFFFF, true},
135 {0x0000FFFF, true},
136 {0xFF0000FF, true},
137 {0x00FFFF00, true},
138 }
139
140 for _, v := range tests {
141 if v.expected != ssa.IsPPC64WordRotateMask(v.input) {
142 t.Errorf("isPPC64WordRotateMask(0x%x) failed", v.input)
143 }
144 }
145 }
146
147 func TestEncodeDecodePPC64WordRotateMask(t *testing.T) {
148 tests := []struct {
149 rotate int64
150 mask uint64
151 nbits,
152 mb,
153 me,
154 encoded int64
155 }{
156 {1, 0x00000001, 32, 31, 31, 0x20011f20},
157 {2, 0x80000001, 32, 31, 0, 0x20021f01},
158 {3, 0xFFFFFFFD, 32, 31, 29, 0x20031f1e},
159 {4, 0x80000000, 32, 0, 0, 0x20040001},
160 {5, 0xFFFFFFFF, 32, 0, 31, 0x20050020},
161 {6, 0x0000FFFF, 32, 16, 31, 0x20061020},
162 {7, 0xFF0000FF, 32, 24, 7, 0x20071808},
163 {8, 0x00FFFF00, 32, 8, 23, 0x20080818},
164
165 {9, 0x0000000000FFFF00, 64, 40, 55, 0x40092838},
166 {10, 0xFFFF000000000000, 64, 0, 15, 0x400A0010},
167 {10, 0xFFFF000000000001, 64, 63, 15, 0x400A3f10},
168 }
169
170 for i, v := range tests {
171 result := ssa.EncodePPC64RotateMask(v.rotate, int64(v.mask), v.nbits)
172 if result != v.encoded {
173 t.Errorf("encodePPC64RotateMask(%d,0x%x,%d) = 0x%x, expected 0x%x", v.rotate, v.mask, v.nbits, result, v.encoded)
174 }
175 rotate, mb, me, mask := ssa.DecodePPC64RotateMask(result)
176 if rotate != v.rotate || mb != v.mb || me != v.me || mask != v.mask {
177 t.Errorf("DecodePPC64Failure(Test %d) got (%d, %d, %d, %x) expected (%d, %d, %d, %x)", i, rotate, mb, me, mask, v.rotate, v.mb, v.me, v.mask)
178 }
179 }
180 }
181
182 func TestMergePPC64ClrlsldiSrw(t *testing.T) {
183 tests := []struct {
184 clrlsldi int32
185 srw int64
186 valid bool
187 rotate int64
188 mask uint64
189 }{
190
191 {ssa.NewPPC64ShiftAuxInt(4, 56, 63, 64), 4, true, 0, 0xFF0},
192
193 {ssa.NewPPC64ShiftAuxInt(4, 48, 63, 64), 4, true, 0, 0xFFFF0},
194
195 {ssa.NewPPC64ShiftAuxInt(17, 48, 63, 64), 4, false, 0, 0},
196
197 {ssa.NewPPC64ShiftAuxInt(16, 48, 63, 64), 4, true, 12, 0xFFFF0000},
198
199 {ssa.NewPPC64ShiftAuxInt(17, 48, 63, 64), 32, false, 0, 0},
200 }
201 for i, v := range tests {
202 result := ssa.MergePPC64ClrlsldiSrw(int64(v.clrlsldi), v.srw)
203 if v.valid && result == 0 {
204 t.Errorf("mergePPC64ClrlsldiSrw(Test %d) did not merge", i)
205 } else if !v.valid && result != 0 {
206 t.Errorf("mergePPC64ClrlsldiSrw(Test %d) should return 0", i)
207 } else if r, _, _, m := ssa.DecodePPC64RotateMask(result); v.rotate != r || v.mask != m {
208 t.Errorf("mergePPC64ClrlsldiSrw(Test %d) got (%d,0x%x) expected (%d,0x%x)", i, r, m, v.rotate, v.mask)
209 }
210 }
211 }
212
213 func TestMergePPC64ClrlsldiRlwinm(t *testing.T) {
214 tests := []struct {
215 clrlsldi int32
216 rlwinm int64
217 valid bool
218 rotate int64
219 mask uint64
220 }{
221
222 {ssa.NewPPC64ShiftAuxInt(4, 56, 63, 64), ssa.EncodePPC64RotateMask(4, 0xFF00, 32), false, 0, 0},
223
224 {ssa.NewPPC64ShiftAuxInt(4, 56, 63, 64), ssa.EncodePPC64RotateMask(28, 0x0FFFFFFF, 32), true, 0, 0xFF0},
225
226 {ssa.NewPPC64ShiftAuxInt(4, 48, 63, 64), ssa.EncodePPC64RotateMask(28, 0xFFFF, 32), true, 0, 0xFFFF0},
227
228 {ssa.NewPPC64ShiftAuxInt(17, 48, 63, 64), ssa.EncodePPC64RotateMask(28, 0xFFFF, 32), false, 0, 0},
229
230 {ssa.NewPPC64ShiftAuxInt(16, 48, 63, 64), ssa.EncodePPC64RotateMask(28, 0xFFFF, 32), true, 12, 0xFFFF0000},
231
232 {ssa.NewPPC64ShiftAuxInt(16, 48, 63, 64), ssa.EncodePPC64RotateMask(28, 0xF000FFFF, 32), true, 12, 0xFFFF0000},
233 }
234 for i, v := range tests {
235 result := ssa.MergePPC64ClrlsldiRlwinm(v.clrlsldi, v.rlwinm)
236 if v.valid && result == 0 {
237 t.Errorf("mergePPC64ClrlsldiRlwinm(Test %d) did not merge", i)
238 } else if !v.valid && result != 0 {
239 t.Errorf("mergePPC64ClrlsldiRlwinm(Test %d) should return 0", i)
240 } else if r, _, _, m := ssa.DecodePPC64RotateMask(result); v.rotate != r || v.mask != m {
241 t.Errorf("mergePPC64ClrlsldiRlwinm(Test %d) got (%d,0x%x) expected (%d,0x%x)", i, r, m, v.rotate, v.mask)
242 }
243 }
244 }
245
246 func TestMergePPC64SldiSrw(t *testing.T) {
247 tests := []struct {
248 sld int64
249 srw int64
250 valid bool
251 rotate int64
252 mask uint64
253 }{
254 {4, 4, true, 0, 0xFFFFFFF0},
255 {4, 8, true, 28, 0x0FFFFFF0},
256 {0, 0, true, 0, 0xFFFFFFFF},
257 {8, 4, false, 0, 0},
258 {0, 32, false, 0, 0},
259 {0, 31, true, 1, 0x1},
260 {31, 31, true, 0, 0x80000000},
261 {32, 32, false, 0, 0},
262 }
263 for i, v := range tests {
264 result := ssa.MergePPC64SldiSrw(v.sld, v.srw)
265 if v.valid && result == 0 {
266 t.Errorf("mergePPC64SldiSrw(Test %d) did not merge", i)
267 } else if !v.valid && result != 0 {
268 t.Errorf("mergePPC64SldiSrw(Test %d) should return 0", i)
269 } else if r, _, _, m := ssa.DecodePPC64RotateMask(result); v.rotate != r || v.mask != m {
270 t.Errorf("mergePPC64SldiSrw(Test %d) got (%d,0x%x) expected (%d,0x%x)", i, r, m, v.rotate, v.mask)
271 }
272 }
273 }
274
275 func TestMergePPC64AndSrwi(t *testing.T) {
276 tests := []struct {
277 and int64
278 srw int64
279 valid bool
280 rotate int64
281 mask uint64
282 }{
283 {0x000000FF, 8, true, 24, 0xFF},
284 {0xF00000FF, 8, true, 24, 0xFF},
285 {0x0F0000FF, 4, false, 0, 0},
286 {0x00000000, 4, false, 0, 0},
287 {0xF0000000, 4, false, 0, 0},
288 {0xF0000000, 32, false, 0, 0},
289 {0xFFFFFFFF, 0, true, 0, 0xFFFFFFFF},
290 }
291 for i, v := range tests {
292 result := ssa.MergePPC64AndSrwi(v.and, v.srw)
293 if v.valid && result == 0 {
294 t.Errorf("mergePPC64AndSrwi(Test %d) did not merge", i)
295 } else if !v.valid && result != 0 {
296 t.Errorf("mergePPC64AndSrwi(Test %d) should return 0", i)
297 } else if r, _, _, m := ssa.DecodePPC64RotateMask(result); v.rotate != r || v.mask != m {
298 t.Errorf("mergePPC64AndSrwi(Test %d) got (%d,0x%x) expected (%d,0x%x)", i, r, m, v.rotate, v.mask)
299 }
300 }
301 }
302
303 func TestDisjointTypes(t *testing.T) {
304 tests := []struct {
305 v1, v2 any
306 expected bool
307 }{
308 {new(int8), new(int8), false},
309 {new(int8), new(float32), false},
310 {new(int8), new(*int8), true},
311 {new(*int8), new(*float32), false},
312 {new(*int8), new(chan<- int8), false},
313 {new(**int8), new(*int8), false},
314 {new(***int8), new(**int8), false},
315 {new(int8), new(chan<- int8), true},
316 {new(int), unsafe.Pointer(nil), false},
317 {new(byte), new(string), false},
318 {new(int), new(string), false},
319 {new(*int8), new(struct{ a, b int }), true},
320 {new(*int8), new(struct {
321 a *int
322 b int
323 }), false},
324 {new(*int8), new(struct {
325 a int
326 b *int
327 }), false},
328 {new(*byte), new(string), false},
329 {new(int), new(struct {
330 a int
331 b *int
332 }), false},
333 {new(float64), new(complex128), false},
334 {new(*byte), new([]byte), false},
335 {new(int), new([]byte), false},
336 {new(int), new([2]*byte), false},
337 {new([2]int), new(*byte), true},
338 }
339 for _, tst := range tests {
340 t1 := rttype.FromReflect(reflect.TypeOf(tst.v1))
341 t2 := rttype.FromReflect(reflect.TypeOf(tst.v2))
342 result := ssa.DisjointTypes(t1, t2)
343 if result != tst.expected {
344 t.Errorf("disjointTypes(%s, %s) got %t expected %t", t1.String(), t2.String(), result, tst.expected)
345 }
346 }
347 }
348
349
350 func foo(p1 *int64, p2 *float64) int64 {
351 *p1 = 10
352 *p2 = 0
353 return *p1
354 }
355
356 func TestDisjointTypesRun(t *testing.T) {
357 f := float64(0)
358 i := (*int64)(unsafe.Pointer(&f))
359 r := foo(i, &f)
360 if r != 0 {
361 t.Errorf("disjointTypes gives an incorrect answer that leads to an incorrect optimization.")
362 }
363 }
364
View as plain text