1
2
3
4
5 package ssacompile
6
7 import (
8 "testing"
9
10 "cmd/compile/internal/ssa"
11 "cmd/compile/internal/ssa/ssahtml"
12 "cmd/compile/internal/ssa/ssaop"
13 "cmd/compile/internal/types"
14 )
15
16 func TestShiftConstAMD64(t *testing.T) {
17 c := testConfig(t)
18 fun := makeConstShiftFunc(c, 18, ssaop.OpLsh64x64, c.config.Types.UInt64)
19 checkOpcodeCounts(t, fun.f, map[ssaop.Op]int{ssaop.OpAMD64SHLQconst: 1, ssaop.OpAMD64CMPQconst: 0, ssaop.OpAMD64ANDQconst: 0})
20
21 fun = makeConstShiftFunc(c, 66, ssaop.OpLsh64x64, c.config.Types.UInt64)
22 checkOpcodeCounts(t, fun.f, map[ssaop.Op]int{ssaop.OpAMD64SHLQconst: 0, ssaop.OpAMD64CMPQconst: 0, ssaop.OpAMD64ANDQconst: 0})
23
24 fun = makeConstShiftFunc(c, 18, ssaop.OpRsh64Ux64, c.config.Types.UInt64)
25 checkOpcodeCounts(t, fun.f, map[ssaop.Op]int{ssaop.OpAMD64SHRQconst: 1, ssaop.OpAMD64CMPQconst: 0, ssaop.OpAMD64ANDQconst: 0})
26
27 fun = makeConstShiftFunc(c, 66, ssaop.OpRsh64Ux64, c.config.Types.UInt64)
28 checkOpcodeCounts(t, fun.f, map[ssaop.Op]int{ssaop.OpAMD64SHRQconst: 0, ssaop.OpAMD64CMPQconst: 0, ssaop.OpAMD64ANDQconst: 0})
29
30 fun = makeConstShiftFunc(c, 18, ssaop.OpRsh64x64, c.config.Types.Int64)
31 checkOpcodeCounts(t, fun.f, map[ssaop.Op]int{ssaop.OpAMD64SARQconst: 1, ssaop.OpAMD64CMPQconst: 0})
32
33 fun = makeConstShiftFunc(c, 66, ssaop.OpRsh64x64, c.config.Types.Int64)
34 checkOpcodeCounts(t, fun.f, map[ssaop.Op]int{ssaop.OpAMD64SARQconst: 1, ssaop.OpAMD64CMPQconst: 0})
35 }
36
37 func makeConstShiftFunc(c *Conf, amount int64, op ssaop.Op, typ *types.Type) fun {
38 ptyp := c.config.Types.BytePtr
39 fun := c.Fun("entry",
40 Bloc("entry",
41 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
42 Valu("SP", ssaop.OpSP, c.config.Types.Uintptr, 0, nil),
43 Valu("argptr", ssaop.OpOffPtr, ptyp, 8, nil, "SP"),
44 Valu("resptr", ssaop.OpOffPtr, ptyp, 16, nil, "SP"),
45 Valu("load", ssaop.OpLoad, typ, 0, nil, "argptr", "mem"),
46 Valu("c", ssaop.OpConst64, c.config.Types.UInt64, amount, nil),
47 Valu("shift", op, typ, 0, nil, "load", "c"),
48 Valu("store", ssaop.OpStore, types.TypeMem, 0, c.config.Types.UInt64, "resptr", "shift", "mem"),
49 Exit("store")))
50 runPasses(fun.f)
51 return fun
52 }
53
54 func TestShiftToExtensionAMD64(t *testing.T) {
55 c := testConfig(t)
56
57
58
59 ops := map[ssaop.Op]int{
60 ssaop.OpAMD64SHLQconst: 0, ssaop.OpAMD64SHLLconst: 0,
61 ssaop.OpAMD64SHRQconst: 0, ssaop.OpAMD64SHRLconst: 0,
62 ssaop.OpAMD64SARQconst: 0, ssaop.OpAMD64SARLconst: 0,
63 }
64 tests := [...]struct {
65 amount int64
66 left, right ssaop.Op
67 typ *types.Type
68 }{
69
70 {56, ssaop.OpLsh64x64, ssaop.OpRsh64Ux64, c.config.Types.UInt64},
71 {48, ssaop.OpLsh64x64, ssaop.OpRsh64Ux64, c.config.Types.UInt64},
72 {32, ssaop.OpLsh64x64, ssaop.OpRsh64Ux64, c.config.Types.UInt64},
73 {24, ssaop.OpLsh32x64, ssaop.OpRsh32Ux64, c.config.Types.UInt32},
74 {16, ssaop.OpLsh32x64, ssaop.OpRsh32Ux64, c.config.Types.UInt32},
75 {8, ssaop.OpLsh16x64, ssaop.OpRsh16Ux64, c.config.Types.UInt16},
76
77 {56, ssaop.OpLsh64x64, ssaop.OpRsh64x64, c.config.Types.Int64},
78 {48, ssaop.OpLsh64x64, ssaop.OpRsh64x64, c.config.Types.Int64},
79 {32, ssaop.OpLsh64x64, ssaop.OpRsh64x64, c.config.Types.Int64},
80 {24, ssaop.OpLsh32x64, ssaop.OpRsh32x64, c.config.Types.Int32},
81 {16, ssaop.OpLsh32x64, ssaop.OpRsh32x64, c.config.Types.Int32},
82 {8, ssaop.OpLsh16x64, ssaop.OpRsh16x64, c.config.Types.Int16},
83 }
84 for _, tc := range tests {
85 fun := makeShiftExtensionFunc(c, tc.amount, tc.left, tc.right, tc.typ)
86 checkOpcodeCounts(t, fun.f, ops)
87 }
88 }
89
90
91
92
93
94
95 func makeShiftExtensionFunc(c *Conf, amount int64, lshift, rshift ssaop.Op, typ *types.Type) fun {
96 ptyp := c.config.Types.BytePtr
97 fun := c.Fun("entry",
98 Bloc("entry",
99 Valu("mem", ssaop.OpInitMem, types.TypeMem, 0, nil),
100 Valu("SP", ssaop.OpSP, c.config.Types.Uintptr, 0, nil),
101 Valu("argptr", ssaop.OpOffPtr, ptyp, 8, nil, "SP"),
102 Valu("resptr", ssaop.OpOffPtr, ptyp, 16, nil, "SP"),
103 Valu("load", ssaop.OpLoad, typ, 0, nil, "argptr", "mem"),
104 Valu("c", ssaop.OpConst64, c.config.Types.UInt64, amount, nil),
105 Valu("lshift", lshift, typ, 0, nil, "load", "c"),
106 Valu("rshift", rshift, typ, 0, nil, "lshift", "c"),
107 Valu("store", ssaop.OpStore, types.TypeMem, 0, c.config.Types.UInt64, "resptr", "rshift", "mem"),
108 Exit("store")))
109 runPasses(fun.f)
110 return fun
111 }
112
113
114
115 func runPasses(f *ssa.Func) {
116 for i := range passes {
117 p := &passes[i]
118 if !f.Config.Optimize && !p.Required || p.Disabled {
119 continue
120 }
121 f.Pass = p
122 f.HTMLWriter = (*ssahtml.HTMLWriter)(nil)
123 p.Fn(f)
124 }
125 }
126
View as plain text