1
2
3
4
5 package ssa
6
7 import (
8 "cmd/compile/internal/abi"
9 "cmd/compile/internal/base"
10 "cmd/compile/internal/ir"
11 "cmd/compile/internal/ssa/ssabase"
12 "cmd/compile/internal/ssa/ssaop"
13 "cmd/compile/internal/types"
14 "cmd/internal/obj"
15 "cmd/internal/src"
16 )
17
18 type (
19 BlockRewriter func(*Block) bool
20 ValueRewriter func(*Value) bool
21 )
22
23
24
25
26 type Config struct {
27 Arch string
28 PtrSize int64
29 RegSize int64
30 Types Types
31 LowerBlock BlockRewriter
32 LowerValue ValueRewriter
33 LateLowerBlock BlockRewriter
34 LateLowerValue ValueRewriter
35 SplitLoad ValueRewriter
36 Registers []ssabase.Register
37 GpRegMask ssaop.RegMask
38 FpRegMask ssaop.RegMask
39 Fp32RegMask ssaop.RegMask
40 Fp64RegMask ssaop.RegMask
41 SimdRegMask ssaop.RegMask
42 SpecialRegMask ssaop.RegMask
43 IntParamRegs []int8
44 FloatParamRegs []int8
45 ABI1 *abi.ABIConfig
46 ABI0 *abi.ABIConfig
47 FPReg int8
48 LinkReg int8
49 HasGReg bool
50 Ctxt *obj.Link
51 Optimize bool
52 SoftFloat bool
53 Race bool
54 BigEndian bool
55 UnalignedOK bool
56 HaveBswap64 bool
57 HaveBswap32 bool
58 HaveBswap16 bool
59 HaveCondSelect bool
60
61
62 MulRecipes map[int64]mulRecipe
63 }
64
65 type Frontend interface {
66 Logger
67
68
69 StringData(string) *obj.LSym
70
71
72
73 SplitSlot(parent *LocalSlot, suffix string, offset int64, t *types.Type) LocalSlot
74
75
76
77 Syslook(string) *obj.LSym
78
79
80 UseWriteBarrier() bool
81
82
83 Func() *ir.Func
84 }
85
86 type Logger interface {
87
88 Logf(string, ...any)
89
90
91
92 Log() bool
93
94
95 Fatalf(pos src.XPos, msg string, args ...any)
96
97
98 Warnl(pos src.XPos, fmt_ string, args ...any)
99
100
101 Debug_checknil() bool
102 }
103
104 type Types struct {
105 Bool *types.Type
106 Int8 *types.Type
107 Int16 *types.Type
108 Int32 *types.Type
109 Int64 *types.Type
110 UInt8 *types.Type
111 UInt16 *types.Type
112 UInt32 *types.Type
113 UInt64 *types.Type
114 Int *types.Type
115 Float32 *types.Type
116 Float64 *types.Type
117 UInt *types.Type
118 Uintptr *types.Type
119 String *types.Type
120 BytePtr *types.Type
121 Int32Ptr *types.Type
122 UInt32Ptr *types.Type
123 IntPtr *types.Type
124 UintptrPtr *types.Type
125 Float32Ptr *types.Type
126 Float64Ptr *types.Type
127 BytePtrPtr *types.Type
128 Vec128 *types.Type
129 Vec256 *types.Type
130 Vec512 *types.Type
131 Mask *types.Type
132 }
133
134 type mulRecipe struct {
135 cost int
136 Build func(*Value, *Value) *Value
137 }
138
139
140 func NewTypes() *Types {
141 t := new(Types)
142 t.SetTypPtrs()
143 return t
144 }
145
146
147 func (t *Types) SetTypPtrs() {
148 t.Bool = types.Types[types.TBOOL]
149 t.Int8 = types.Types[types.TINT8]
150 t.Int16 = types.Types[types.TINT16]
151 t.Int32 = types.Types[types.TINT32]
152 t.Int64 = types.Types[types.TINT64]
153 t.UInt8 = types.Types[types.TUINT8]
154 t.UInt16 = types.Types[types.TUINT16]
155 t.UInt32 = types.Types[types.TUINT32]
156 t.UInt64 = types.Types[types.TUINT64]
157 t.Int = types.Types[types.TINT]
158 t.Float32 = types.Types[types.TFLOAT32]
159 t.Float64 = types.Types[types.TFLOAT64]
160 t.UInt = types.Types[types.TUINT]
161 t.Uintptr = types.Types[types.TUINTPTR]
162 t.String = types.Types[types.TSTRING]
163 t.BytePtr = types.NewPtr(types.Types[types.TUINT8])
164 t.Int32Ptr = types.NewPtr(types.Types[types.TINT32])
165 t.UInt32Ptr = types.NewPtr(types.Types[types.TUINT32])
166 t.IntPtr = types.NewPtr(types.Types[types.TINT])
167 t.UintptrPtr = types.NewPtr(types.Types[types.TUINTPTR])
168 t.Float32Ptr = types.NewPtr(types.Types[types.TFLOAT32])
169 t.Float64Ptr = types.NewPtr(types.Types[types.TFLOAT64])
170 t.BytePtrPtr = types.NewPtr(types.NewPtr(types.Types[types.TUINT8]))
171 t.Vec128 = types.TypeVec128
172 t.Vec256 = types.TypeVec256
173 t.Vec512 = types.TypeVec512
174 t.Mask = types.TypeMask
175 }
176
177 func (c *Config) HaveByteSwap(size int64) bool {
178 switch size {
179 case 8:
180 return c.HaveBswap64
181 case 4:
182 return c.HaveBswap32
183 case 2:
184 return c.HaveBswap16
185 default:
186 base.Fatalf("bad size %d\n", size)
187 return false
188 }
189 }
190
191 func (c *Config) BuildRecipes(arch string) {
192
193 type linearCombo struct {
194
195 a, b int64
196
197 cost int
198
199
200 build func(m, x, y *Value) *Value
201 }
202
203
204 var linearCombos []linearCombo
205 r := func(a, b int64, cost int, build func(m, x, y *Value) *Value) {
206 linearCombos = append(linearCombos, linearCombo{a: a, b: b, cost: cost, build: build})
207 }
208 var mulCost int
209 switch arch {
210 case "amd64":
211
212
213
214
215
216
217 mulCost = 30
218
219 r(1, 1, 10,
220 func(m, x, y *Value) *Value {
221 v := m.Block.NewValue2(m.Pos, ssaop.OpAMD64ADDQ, m.Type, x, y)
222 if m.Type.Size() == 4 {
223 v.Op = ssaop.OpAMD64ADDL
224 }
225 return v
226 })
227
228 r(-1, 0, 11,
229 func(m, x, y *Value) *Value {
230 v := m.Block.NewValue1(m.Pos, ssaop.OpAMD64NEGQ, m.Type, x)
231 if m.Type.Size() == 4 {
232 v.Op = ssaop.OpAMD64NEGL
233 }
234 return v
235 })
236
237 r(1, -1, 11,
238 func(m, x, y *Value) *Value {
239 v := m.Block.NewValue2(m.Pos, ssaop.OpAMD64SUBQ, m.Type, x, y)
240 if m.Type.Size() == 4 {
241 v.Op = ssaop.OpAMD64SUBL
242 }
243 return v
244 })
245
246 r(1, 2, 10,
247 func(m, x, y *Value) *Value {
248 v := m.Block.NewValue2(m.Pos, ssaop.OpAMD64LEAQ2, m.Type, x, y)
249 if m.Type.Size() == 4 {
250 v.Op = ssaop.OpAMD64LEAL2
251 }
252 return v
253 })
254 r(1, 4, 10,
255 func(m, x, y *Value) *Value {
256 v := m.Block.NewValue2(m.Pos, ssaop.OpAMD64LEAQ4, m.Type, x, y)
257 if m.Type.Size() == 4 {
258 v.Op = ssaop.OpAMD64LEAL4
259 }
260 return v
261 })
262 r(1, 8, 10,
263 func(m, x, y *Value) *Value {
264 v := m.Block.NewValue2(m.Pos, ssaop.OpAMD64LEAQ8, m.Type, x, y)
265 if m.Type.Size() == 4 {
266 v.Op = ssaop.OpAMD64LEAL8
267 }
268 return v
269 })
270
271 for i := 2; i < 64; i++ {
272 r(1<<i, 0, 11,
273 func(m, x, y *Value) *Value {
274 v := m.Block.NewValue1I(m.Pos, ssaop.OpAMD64SHLQconst, m.Type, int64(i), x)
275 if m.Type.Size() == 4 {
276 v.Op = ssaop.OpAMD64SHLLconst
277 }
278 return v
279 })
280 }
281
282 case "arm64":
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 mulCost = 35
298
299 r(1, 1, 10,
300 func(m, x, y *Value) *Value {
301 return m.Block.NewValue2(m.Pos, ssaop.OpARM64ADD, m.Type, x, y)
302 })
303
304 r(-1, 0, 10,
305 func(m, x, y *Value) *Value {
306 return m.Block.NewValue1(m.Pos, ssaop.OpARM64NEG, m.Type, x)
307 })
308
309 r(1, -1, 10,
310 func(m, x, y *Value) *Value {
311 return m.Block.NewValue2(m.Pos, ssaop.OpARM64SUB, m.Type, x, y)
312 })
313
314 for i := 1; i < 64; i++ {
315 c := 20
316 if i > 4 {
317 c++
318 }
319 r(1, 1<<i, c,
320 func(m, x, y *Value) *Value {
321 return m.Block.NewValue2I(m.Pos, ssaop.OpARM64ADDshiftLL, m.Type, int64(i), x, y)
322 })
323 }
324
325 for i := 1; i < 64; i++ {
326 c := 20
327 if i > 4 {
328 c++
329 }
330 r(-1<<i, 0, c,
331 func(m, x, y *Value) *Value {
332 return m.Block.NewValue1I(m.Pos, ssaop.OpARM64NEGshiftLL, m.Type, int64(i), x)
333 })
334 }
335
336 for i := 1; i < 64; i++ {
337 c := 20
338 if i > 4 {
339 c++
340 }
341 r(1, -1<<i, c,
342 func(m, x, y *Value) *Value {
343 return m.Block.NewValue2I(m.Pos, ssaop.OpARM64SUBshiftLL, m.Type, int64(i), x, y)
344 })
345 }
346
347 for i := 1; i < 64; i++ {
348 c := 10
349 if i == 1 {
350
351
352
353 c--
354 }
355 r(1<<i, 0, c,
356 func(m, x, y *Value) *Value {
357 return m.Block.NewValue1I(m.Pos, ssaop.OpARM64SLLconst, m.Type, int64(i), x)
358 })
359 }
360 case "loong64":
361
362
363
364
365 mulCost = 45
366
367
368 r(1, 1, 10,
369 func(m, x, y *Value) *Value {
370 return m.Block.NewValue2(m.Pos, ssaop.OpLOONG64ADDV, m.Type, x, y)
371 })
372
373 r(-1, 0, 10,
374 func(m, x, y *Value) *Value {
375 return m.Block.NewValue1(m.Pos, ssaop.OpLOONG64NEGV, m.Type, x)
376 })
377
378 r(1, -1, 10,
379 func(m, x, y *Value) *Value {
380 return m.Block.NewValue2(m.Pos, ssaop.OpLOONG64SUBV, m.Type, x, y)
381 })
382
383
384 for i := 1; i < 5; i++ {
385 c := 10
386 r(1, 1<<i, c,
387 func(m, x, y *Value) *Value {
388 return m.Block.NewValue2I(m.Pos, ssaop.OpLOONG64ADDshiftLLV, m.Type, int64(i), x, y)
389 })
390 }
391
392
393 for i := 1; i < 64; i++ {
394 c := 10
395 if i == 1 {
396
397
398
399 c--
400 }
401 r(1<<i, 0, c,
402 func(m, x, y *Value) *Value {
403 return m.Block.NewValue1I(m.Pos, ssaop.OpLOONG64SLLVconst, m.Type, int64(i), x)
404 })
405 }
406 }
407
408 c.MulRecipes = map[int64]mulRecipe{}
409
410
411
412 for _, combo := range linearCombos {
413 x := combo.a + combo.b
414 cost := combo.cost
415 old := c.MulRecipes[x]
416 if (old.Build == nil || cost < old.cost) && cost < mulCost {
417 c.MulRecipes[x] = mulRecipe{cost: cost, Build: func(m, v *Value) *Value {
418 return combo.build(m, v, v)
419 }}
420 }
421 }
422
423
424
425
426
427
428
429
430 for _, inner := range linearCombos {
431 for _, outer := range linearCombos {
432 x := (inner.a + inner.b) * (outer.a + outer.b)
433 cost := inner.cost + outer.cost
434 old := c.MulRecipes[x]
435 if (old.Build == nil || cost < old.cost) && cost < mulCost {
436 c.MulRecipes[x] = mulRecipe{cost: cost, Build: func(m, v *Value) *Value {
437 v = inner.build(m, v, v)
438 return outer.build(m, v, v)
439 }}
440 }
441 }
442 }
443
444
445 for _, inner := range linearCombos {
446 for _, outer := range linearCombos {
447 x := outer.a + outer.b*(inner.a+inner.b)
448 cost := inner.cost + outer.cost
449 old := c.MulRecipes[x]
450 if (old.Build == nil || cost < old.cost) && cost < mulCost {
451 c.MulRecipes[x] = mulRecipe{cost: cost, Build: func(m, v *Value) *Value {
452 return outer.build(m, v, inner.build(m, v, v))
453 }}
454 }
455 }
456 }
457
458
459 for _, inner := range linearCombos {
460 for _, outer := range linearCombos {
461 x := outer.a*(inner.a+inner.b) + outer.b
462 cost := inner.cost + outer.cost
463 old := c.MulRecipes[x]
464 if (old.Build == nil || cost < old.cost) && cost < mulCost {
465 c.MulRecipes[x] = mulRecipe{cost: cost, Build: func(m, v *Value) *Value {
466 return outer.build(m, inner.build(m, v, v), v)
467 }}
468 }
469 }
470 }
471
472
473 if arch == "loong64" {
474
475
476
477
478
479 for _, first := range linearCombos {
480 for _, second := range linearCombos {
481 for _, third := range linearCombos {
482 x := third.a*(first.a+first.b) + third.b*(second.a+second.b)
483 cost := first.cost + second.cost + third.cost
484 old := c.MulRecipes[x]
485 if (old.Build == nil || cost < old.cost) && cost < mulCost {
486 c.MulRecipes[x] = mulRecipe{cost: cost, Build: func(m, v *Value) *Value {
487 v1 := first.build(m, v, v)
488 v2 := second.build(m, v, v)
489 return third.build(m, v1, v2)
490 }}
491 }
492 }
493 }
494 }
495
496
497 for _, first := range linearCombos {
498 for _, second := range linearCombos {
499 for _, third := range linearCombos {
500 x := third.a*(second.a*(first.a+first.b)+second.b) + third.b
501 cost := first.cost + second.cost + third.cost
502 old := c.MulRecipes[x]
503 if (old.Build == nil || cost < old.cost) && cost < mulCost {
504 c.MulRecipes[x] = mulRecipe{cost: cost, Build: func(m, v *Value) *Value {
505 v1 := first.build(m, v, v)
506 v2 := second.build(m, v1, v)
507 return third.build(m, v2, v)
508 }}
509 }
510 }
511 }
512 }
513 }
514
515
516
517 delete(c.MulRecipes, 0)
518 delete(c.MulRecipes, 1)
519
520
521
522
523
524
525
526 }
527
View as plain text