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