]> Cypherpunks.ru repositories - gostls13.git/blob - test/codegen/shift.go
cmd/compile: optimize right shifts of int32 on riscv64
[gostls13.git] / test / codegen / shift.go
1 // asmcheck
2
3 // Copyright 2018 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 package codegen
8
9 // ------------------ //
10 //   constant shifts  //
11 // ------------------ //
12
13 func lshConst64x64(v int64) int64 {
14         // ppc64x:"SLD"
15         // riscv64:"SLLI",-"AND",-"SLTIU"
16         return v << uint64(33)
17 }
18
19 func rshConst64Ux64(v uint64) uint64 {
20         // ppc64x:"SRD"
21         // riscv64:"SRLI\t",-"AND",-"SLTIU"
22         return v >> uint64(33)
23 }
24
25 func rshConst64x64(v int64) int64 {
26         // ppc64x:"SRAD"
27         // riscv64:"SRAI\t",-"OR",-"SLTIU"
28         return v >> uint64(33)
29 }
30
31 func lshConst32x64(v int32) int32 {
32         // ppc64x:"SLW"
33         // riscv64:"SLLI",-"AND",-"SLTIU", -"MOVW"
34         return v << uint64(29)
35 }
36
37 func rshConst32Ux64(v uint32) uint32 {
38         // ppc64x:"SRW"
39         // riscv64:"SRLIW",-"AND",-"SLTIU", -"MOVW"
40         return v >> uint64(29)
41 }
42
43 func rshConst32x64(v int32) int32 {
44         // ppc64x:"SRAW"
45         // riscv64:"SRAIW",-"OR",-"SLTIU", -"MOVW"
46         return v >> uint64(29)
47 }
48
49 func lshConst64x32(v int64) int64 {
50         // ppc64x:"SLD"
51         // riscv64:"SLLI",-"AND",-"SLTIU"
52         return v << uint32(33)
53 }
54
55 func rshConst64Ux32(v uint64) uint64 {
56         // ppc64x:"SRD"
57         // riscv64:"SRLI\t",-"AND",-"SLTIU"
58         return v >> uint32(33)
59 }
60
61 func rshConst64x32(v int64) int64 {
62         // ppc64x:"SRAD"
63         // riscv64:"SRAI\t",-"OR",-"SLTIU"
64         return v >> uint32(33)
65 }
66
67 // ------------------ //
68 //   masked shifts    //
69 // ------------------ //
70
71 func lshMask64x64(v int64, s uint64) int64 {
72         // arm64:"LSL",-"AND"
73         // ppc64x:"RLDICL",-"ORN",-"ISEL"
74         // riscv64:"SLL",-"AND\t",-"SLTIU"
75         // s390x:-"RISBGZ",-"AND",-"LOCGR"
76         return v << (s & 63)
77 }
78
79 func rshMask64Ux64(v uint64, s uint64) uint64 {
80         // arm64:"LSR",-"AND",-"CSEL"
81         // ppc64x:"RLDICL",-"ORN",-"ISEL"
82         // riscv64:"SRL\t",-"AND\t",-"SLTIU"
83         // s390x:-"RISBGZ",-"AND",-"LOCGR"
84         return v >> (s & 63)
85 }
86
87 func rshMask64x64(v int64, s uint64) int64 {
88         // arm64:"ASR",-"AND",-"CSEL"
89         // ppc64x:"RLDICL",-"ORN",-"ISEL"
90         // riscv64:"SRA\t",-"OR",-"SLTIU"
91         // s390x:-"RISBGZ",-"AND",-"LOCGR"
92         return v >> (s & 63)
93 }
94
95 func lshMask32x64(v int32, s uint64) int32 {
96         // arm64:"LSL",-"AND"
97         // ppc64x:"ISEL",-"ORN"
98         // riscv64:"SLL",-"AND\t",-"SLTIU"
99         // s390x:-"RISBGZ",-"AND",-"LOCGR"
100         return v << (s & 63)
101 }
102
103 func rshMask32Ux64(v uint32, s uint64) uint32 {
104         // arm64:"LSR",-"AND"
105         // ppc64x:"ISEL",-"ORN"
106         // riscv64:"SRLW","SLTIU","NEG","AND\t",-"SRL\t"
107         // s390x:-"RISBGZ",-"AND",-"LOCGR"
108         return v >> (s & 63)
109 }
110
111 func rsh5Mask32Ux64(v uint32, s uint64) uint32 {
112         // riscv64:"SRLW",-"AND\t",-"SLTIU",-"SRL\t"
113         return v >> (s & 31)
114 }
115
116 func rshMask32x64(v int32, s uint64) int32 {
117         // arm64:"ASR",-"AND"
118         // ppc64x:"ISEL",-"ORN"
119         // riscv64:"SRAW","OR","SLTIU"
120         // s390x:-"RISBGZ",-"AND",-"LOCGR"
121         return v >> (s & 63)
122 }
123
124 func rsh5Mask32x64(v int32, s uint64) int32 {
125         // riscv64:"SRAW",-"OR",-"SLTIU"
126         return v >> (s & 31)
127 }
128
129 func lshMask64x32(v int64, s uint32) int64 {
130         // arm64:"LSL",-"AND"
131         // ppc64x:"RLDICL",-"ORN"
132         // riscv64:"SLL",-"AND\t",-"SLTIU"
133         // s390x:-"RISBGZ",-"AND",-"LOCGR"
134         return v << (s & 63)
135 }
136
137 func rshMask64Ux32(v uint64, s uint32) uint64 {
138         // arm64:"LSR",-"AND",-"CSEL"
139         // ppc64x:"RLDICL",-"ORN"
140         // riscv64:"SRL\t",-"AND\t",-"SLTIU"
141         // s390x:-"RISBGZ",-"AND",-"LOCGR"
142         return v >> (s & 63)
143 }
144
145 func rshMask64x32(v int64, s uint32) int64 {
146         // arm64:"ASR",-"AND",-"CSEL"
147         // ppc64x:"RLDICL",-"ORN",-"ISEL"
148         // riscv64:"SRA\t",-"OR",-"SLTIU"
149         // s390x:-"RISBGZ",-"AND",-"LOCGR"
150         return v >> (s & 63)
151 }
152
153 func lshMask64x32Ext(v int64, s int32) int64 {
154         // ppc64x:"RLDICL",-"ORN",-"ISEL"
155         // riscv64:"SLL",-"AND\t",-"SLTIU"
156         // s390x:-"RISBGZ",-"AND",-"LOCGR"
157         return v << uint(s&63)
158 }
159
160 func rshMask64Ux32Ext(v uint64, s int32) uint64 {
161         // ppc64x:"RLDICL",-"ORN",-"ISEL"
162         // riscv64:"SRL\t",-"AND\t",-"SLTIU"
163         // s390x:-"RISBGZ",-"AND",-"LOCGR"
164         return v >> uint(s&63)
165 }
166
167 func rshMask64x32Ext(v int64, s int32) int64 {
168         // ppc64x:"RLDICL",-"ORN",-"ISEL"
169         // riscv64:"SRA\t",-"OR",-"SLTIU"
170         // s390x:-"RISBGZ",-"AND",-"LOCGR"
171         return v >> uint(s&63)
172 }
173
174 // --------------- //
175 //  signed shifts  //
176 // --------------- //
177
178 // We do want to generate a test + panicshift for these cases.
179 func lshSigned(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
180         // amd64:"TESTB"
181         _ = x << v8
182         // amd64:"TESTW"
183         _ = x << v16
184         // amd64:"TESTL"
185         _ = x << v32
186         // amd64:"TESTQ"
187         _ = x << v64
188 }
189
190 // We want to avoid generating a test + panicshift for these cases.
191 func lshSignedMasked(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
192         // amd64:-"TESTB"
193         _ = x << (v8 & 7)
194         // amd64:-"TESTW"
195         _ = x << (v16 & 15)
196         // amd64:-"TESTL"
197         _ = x << (v32 & 31)
198         // amd64:-"TESTQ"
199         _ = x << (v64 & 63)
200 }
201
202 // ------------------ //
203 //   bounded shifts   //
204 // ------------------ //
205
206 func lshGuarded64(v int64, s uint) int64 {
207         if s < 64 {
208                 // riscv64:"SLL",-"AND",-"SLTIU"
209                 // s390x:-"RISBGZ",-"AND",-"LOCGR"
210                 // wasm:-"Select",-".*LtU"
211                 // arm64:"LSL",-"CSEL"
212                 return v << s
213         }
214         panic("shift too large")
215 }
216
217 func rshGuarded64U(v uint64, s uint) uint64 {
218         if s < 64 {
219                 // riscv64:"SRL\t",-"AND",-"SLTIU"
220                 // s390x:-"RISBGZ",-"AND",-"LOCGR"
221                 // wasm:-"Select",-".*LtU"
222                 // arm64:"LSR",-"CSEL"
223                 return v >> s
224         }
225         panic("shift too large")
226 }
227
228 func rshGuarded64(v int64, s uint) int64 {
229         if s < 64 {
230                 // riscv64:"SRA\t",-"OR",-"SLTIU"
231                 // s390x:-"RISBGZ",-"AND",-"LOCGR"
232                 // wasm:-"Select",-".*LtU"
233                 // arm64:"ASR",-"CSEL"
234                 return v >> s
235         }
236         panic("shift too large")
237 }
238
239 func provedUnsignedShiftLeft(val64 uint64, val32 uint32, val16 uint16, val8 uint8, shift int) (r1 uint64, r2 uint32, r3 uint16, r4 uint8) {
240         if shift >= 0 && shift < 64 {
241                 // arm64:"LSL",-"CSEL"
242                 r1 = val64 << shift
243         }
244         if shift >= 0 && shift < 32 {
245                 // arm64:"LSL",-"CSEL"
246                 r2 = val32 << shift
247         }
248         if shift >= 0 && shift < 16 {
249                 // arm64:"LSL",-"CSEL"
250                 r3 = val16 << shift
251         }
252         if shift >= 0 && shift < 8 {
253                 // arm64:"LSL",-"CSEL"
254                 r4 = val8 << shift
255         }
256         return r1, r2, r3, r4
257 }
258
259 func provedSignedShiftLeft(val64 int64, val32 int32, val16 int16, val8 int8, shift int) (r1 int64, r2 int32, r3 int16, r4 int8) {
260         if shift >= 0 && shift < 64 {
261                 // arm64:"LSL",-"CSEL"
262                 r1 = val64 << shift
263         }
264         if shift >= 0 && shift < 32 {
265                 // arm64:"LSL",-"CSEL"
266                 r2 = val32 << shift
267         }
268         if shift >= 0 && shift < 16 {
269                 // arm64:"LSL",-"CSEL"
270                 r3 = val16 << shift
271         }
272         if shift >= 0 && shift < 8 {
273                 // arm64:"LSL",-"CSEL"
274                 r4 = val8 << shift
275         }
276         return r1, r2, r3, r4
277 }
278
279 func provedUnsignedShiftRight(val64 uint64, val32 uint32, val16 uint16, val8 uint8, shift int) (r1 uint64, r2 uint32, r3 uint16, r4 uint8) {
280         if shift >= 0 && shift < 64 {
281                 // arm64:"LSR",-"CSEL"
282                 r1 = val64 >> shift
283         }
284         if shift >= 0 && shift < 32 {
285                 // arm64:"LSR",-"CSEL"
286                 r2 = val32 >> shift
287         }
288         if shift >= 0 && shift < 16 {
289                 // arm64:"LSR",-"CSEL"
290                 r3 = val16 >> shift
291         }
292         if shift >= 0 && shift < 8 {
293                 // arm64:"LSR",-"CSEL"
294                 r4 = val8 >> shift
295         }
296         return r1, r2, r3, r4
297 }
298
299 func provedSignedShiftRight(val64 int64, val32 int32, val16 int16, val8 int8, shift int) (r1 int64, r2 int32, r3 int16, r4 int8) {
300         if shift >= 0 && shift < 64 {
301                 // arm64:"ASR",-"CSEL"
302                 r1 = val64 >> shift
303         }
304         if shift >= 0 && shift < 32 {
305                 // arm64:"ASR",-"CSEL"
306                 r2 = val32 >> shift
307         }
308         if shift >= 0 && shift < 16 {
309                 // arm64:"ASR",-"CSEL"
310                 r3 = val16 >> shift
311         }
312         if shift >= 0 && shift < 8 {
313                 // arm64:"ASR",-"CSEL"
314                 r4 = val8 >> shift
315         }
316         return r1, r2, r3, r4
317 }
318
319 func checkUnneededTrunc(tab *[100000]uint32, d uint64, v uint32, h uint16, b byte) (uint32, uint64) {
320
321         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
322         f := tab[byte(v)^b]
323         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
324         f += tab[byte(v)&b]
325         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
326         f += tab[byte(v)|b]
327         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
328         f += tab[uint16(v)&h]
329         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
330         f += tab[uint16(v)^h]
331         // ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
332         f += tab[uint16(v)|h]
333         // ppc64x:-".*AND",-"RLDICR",".*CLRLSLDI"
334         f += tab[v&0xff]
335         // ppc64x:-".*AND",".*CLRLSLWI"
336         f += 2 * uint32(uint16(d))
337         // ppc64x:-".*AND",-"RLDICR",".*CLRLSLDI"
338         g := 2 * uint64(uint32(d))
339         return f, g
340 }
341
342 func checkCombinedShifts(v8 uint8, v16 uint16, v32 uint32, x32 int32, v64 uint64) (uint8, uint16, uint32, uint64, int64) {
343
344         // ppc64x:-"AND","CLRLSLWI"
345         f := (v8 & 0xF) << 2
346         // ppc64x:"CLRLSLWI"
347         f += byte(v16) << 3
348         // ppc64x:-"AND","CLRLSLWI"
349         g := (v16 & 0xFF) << 3
350         // ppc64x:-"AND","CLRLSLWI"
351         h := (v32 & 0xFFFFF) << 2
352         // ppc64x:"CLRLSLDI"
353         i := (v64 & 0xFFFFFFFF) << 5
354         // ppc64x:-"CLRLSLDI"
355         i += (v64 & 0xFFFFFFF) << 38
356         // ppc64x/power9:-"CLRLSLDI"
357         i += (v64 & 0xFFFF00) << 10
358         // ppc64x/power9:-"SLD","EXTSWSLI"
359         j := int64(x32+32) * 8
360         return f, g, h, i, j
361 }
362
363 func checkWidenAfterShift(v int64, u uint64) (int64, uint64) {
364
365         // ppc64x:-".*MOVW"
366         f := int32(v >> 32)
367         // ppc64x:".*MOVW"
368         f += int32(v >> 31)
369         // ppc64x:-".*MOVH"
370         g := int16(v >> 48)
371         // ppc64x:".*MOVH"
372         g += int16(v >> 30)
373         // ppc64x:-".*MOVH"
374         g += int16(f >> 16)
375         // ppc64x:-".*MOVB"
376         h := int8(v >> 56)
377         // ppc64x:".*MOVB"
378         h += int8(v >> 28)
379         // ppc64x:-".*MOVB"
380         h += int8(f >> 24)
381         // ppc64x:".*MOVB"
382         h += int8(f >> 16)
383         return int64(h), uint64(g)
384 }
385
386 func checkShiftAndMask32(v []uint32) {
387         i := 0
388
389         // ppc64x: "RLWNM\t[$]24, R[0-9]+, [$]12, [$]19, R[0-9]+"
390         v[i] = (v[i] & 0xFF00000) >> 8
391         i++
392         // ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]22, [$]29, R[0-9]+"
393         v[i] = (v[i] & 0xFF00) >> 6
394         i++
395         // ppc64x: "MOVW\tR0"
396         v[i] = (v[i] & 0xFF) >> 8
397         i++
398         // ppc64x: "MOVW\tR0"
399         v[i] = (v[i] & 0xF000000) >> 28
400         i++
401         // ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]24, [$]31, R[0-9]+"
402         v[i] = (v[i] >> 6) & 0xFF
403         i++
404         // ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]12, [$]19, R[0-9]+"
405         v[i] = (v[i] >> 6) & 0xFF000
406         i++
407         // ppc64x: "MOVW\tR0"
408         v[i] = (v[i] >> 20) & 0xFF000
409         i++
410         // ppc64x: "MOVW\tR0"
411         v[i] = (v[i] >> 24) & 0xFF00
412         i++
413 }
414
415 func checkMergedShifts32(a [256]uint32, b [256]uint64, u uint32, v uint32) {
416         // ppc64x: -"CLRLSLDI", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]29, R[0-9]+"
417         a[0] = a[uint8(v>>24)]
418         // ppc64x: -"CLRLSLDI", "RLWNM\t[$]11, R[0-9]+, [$]21, [$]28, R[0-9]+"
419         b[0] = b[uint8(v>>24)]
420         // ppc64x: -"CLRLSLDI", "RLWNM\t[$]15, R[0-9]+, [$]21, [$]28, R[0-9]+"
421         b[1] = b[(v>>20)&0xFF]
422         // ppc64x: -"SLD", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]28, R[0-9]+"
423         b[2] = b[v>>25]
424 }
425
426 // 128 bit shifts
427
428 func check128bitShifts(x, y uint64, bits uint) (uint64, uint64) {
429         s := bits & 63
430         ŝ := (64 - bits) & 63
431         // check that the shift operation has two commas (three operands)
432         // amd64:"SHRQ.*,.*,"
433         shr := x>>s | y<<ŝ
434         // amd64:"SHLQ.*,.*,"
435         shl := x<<s | y>>ŝ
436         return shr, shl
437 }
438
439 func checkShiftToMask(u []uint64, s []int64) {
440         // amd64:-"SHR",-"SHL","ANDQ"
441         u[0] = u[0] >> 5 << 5
442         // amd64:-"SAR",-"SHL","ANDQ"
443         s[0] = s[0] >> 5 << 5
444         // amd64:-"SHR",-"SHL","ANDQ"
445         u[1] = u[1] << 5 >> 5
446 }