1
2
3
4
5 package inlheur
6
7 import (
8 "cmd/compile/internal/ir"
9 "cmd/compile/internal/typecheck"
10 "cmd/compile/internal/types"
11 "cmd/internal/src"
12 "go/constant"
13 "testing"
14 )
15
16 var pos src.XPos
17 var local *types.Pkg
18 var f *ir.Func
19
20 func init() {
21 types.PtrSize = 8
22 types.RegSize = 8
23 types.MaxWidth = 1 << 50
24 typecheck.InitUniverse()
25 local = types.NewPkg("", "")
26 fsym := &types.Sym{
27 Pkg: types.NewPkg("my/import/path", "path"),
28 Name: "function",
29 }
30 f = ir.NewFunc(src.NoXPos, src.NoXPos, fsym, nil)
31 }
32
33 type state struct {
34 ntab map[string]*ir.Name
35 }
36
37 func mkstate() *state {
38 return &state{
39 ntab: make(map[string]*ir.Name),
40 }
41 }
42
43 func bin(x ir.Node, op ir.Op, y ir.Node) ir.Node {
44 return ir.NewBinaryExpr(pos, op, x, y)
45 }
46
47 func conv(x ir.Node, t *types.Type) ir.Node {
48 return ir.NewConvExpr(pos, ir.OCONV, t, x)
49 }
50
51 func logical(x ir.Node, op ir.Op, y ir.Node) ir.Node {
52 return ir.NewLogicalExpr(pos, op, x, y)
53 }
54
55 func un(op ir.Op, x ir.Node) ir.Node {
56 return ir.NewUnaryExpr(pos, op, x)
57 }
58
59 func liti(i int64) ir.Node {
60 return ir.NewBasicLit(pos, types.Types[types.TINT64], constant.MakeInt64(i))
61 }
62
63 func lits(s string) ir.Node {
64 return ir.NewBasicLit(pos, types.Types[types.TSTRING], constant.MakeString(s))
65 }
66
67 func (s *state) nm(name string, t *types.Type) *ir.Name {
68 if n, ok := s.ntab[name]; ok {
69 if n.Type() != t {
70 panic("bad")
71 }
72 return n
73 }
74 sym := local.Lookup(name)
75 nn := ir.NewNameAt(pos, sym, t)
76 s.ntab[name] = nn
77 return nn
78 }
79
80 func (s *state) nmi64(name string) *ir.Name {
81 return s.nm(name, types.Types[types.TINT64])
82 }
83
84 func (s *state) nms(name string) *ir.Name {
85 return s.nm(name, types.Types[types.TSTRING])
86 }
87
88 func TestClassifyIntegerCompare(t *testing.T) {
89
90
91 s := mkstate()
92 nn := s.nmi64("n")
93 nlt10 := bin(nn, ir.OLT, liti(10))
94 ngt100 := bin(nn, ir.OGT, liti(100))
95 nge12 := bin(nn, ir.OGE, liti(12))
96 nle99 := bin(nn, ir.OLE, liti(99))
97 nne101 := bin(nn, ir.ONE, liti(101))
98 noror1 := logical(nlt10, ir.OOROR, ngt100)
99 noror2 := logical(nge12, ir.OOROR, nle99)
100 noror3 := logical(noror2, ir.OOROR, nne101)
101 nandand := typecheck.Expr(logical(noror1, ir.OANDAND, noror3))
102
103 wantv := true
104 v := ShouldFoldIfNameConstant(nandand, []*ir.Name{nn})
105 if v != wantv {
106 t.Errorf("wanted shouldfold(%v) %v, got %v", nandand, wantv, v)
107 }
108 }
109
110 func TestClassifyStringCompare(t *testing.T) {
111
112
113 s := mkstate()
114 nn := s.nms("s")
115 snefoo := bin(nn, ir.ONE, lits("foo"))
116 sltoob := bin(nn, ir.OLT, lits("ooblek"))
117 sgtpk := bin(nn, ir.OGT, lits("plarkish"))
118 nandand := logical(snefoo, ir.OANDAND, sltoob)
119 top := typecheck.Expr(logical(nandand, ir.OANDAND, sgtpk))
120
121 wantv := true
122 v := ShouldFoldIfNameConstant(top, []*ir.Name{nn})
123 if v != wantv {
124 t.Errorf("wanted shouldfold(%v) %v, got %v", top, wantv, v)
125 }
126 }
127
128 func TestClassifyIntegerArith(t *testing.T) {
129
130
131 s := mkstate()
132 nn := s.nmi64("n")
133 np1 := bin(nn, ir.OADD, liti(1))
134 nm3 := bin(nn, ir.OSUB, liti(3))
135 nd2 := bin(nn, ir.ODIV, liti(2))
136 nls9 := bin(nn, ir.OLSH, liti(9))
137 nrs2 := bin(nn, ir.ORSH, liti(2))
138 nan7 := bin(nn, ir.OANDNOT, liti(7))
139 c1xor := bin(np1, ir.OXOR, nm3)
140 c2mul := bin(c1xor, ir.OMUL, nd2)
141 c3add := bin(c2mul, ir.OADD, nls9)
142 c4add := bin(c3add, ir.OADD, nrs2)
143 c5sub := bin(c4add, ir.OSUB, nan7)
144 top := typecheck.Expr(c5sub)
145
146 wantv := true
147 v := ShouldFoldIfNameConstant(top, []*ir.Name{nn})
148 if v != wantv {
149 t.Errorf("wanted shouldfold(%v) %v, got %v", top, wantv, v)
150 }
151 }
152
153 func TestClassifyAssortedShifts(t *testing.T) {
154
155 s := mkstate()
156 nn := s.nmi64("n")
157 badcases := []ir.Node{
158 bin(liti(3), ir.OLSH, nn),
159 bin(liti(7), ir.ORSH, nn),
160 }
161 for _, bc := range badcases {
162 wantv := false
163 v := ShouldFoldIfNameConstant(typecheck.Expr(bc), []*ir.Name{nn})
164 if v != wantv {
165 t.Errorf("wanted shouldfold(%v) %v, got %v", bc, wantv, v)
166 }
167 }
168 }
169
170 func TestClassifyFloat(t *testing.T) {
171
172 s := mkstate()
173 nn := s.nm("n", types.Types[types.TUINT32])
174 f1 := conv(nn, types.Types[types.TFLOAT32])
175 f2 := conv(liti(10), types.Types[types.TFLOAT32])
176 add := bin(f1, ir.OADD, f2)
177
178 wantv := false
179 v := ShouldFoldIfNameConstant(typecheck.Expr(add), []*ir.Name{nn})
180 if v != wantv {
181 t.Errorf("wanted shouldfold(%v) %v, got %v", add, wantv, v)
182 }
183 }
184
185 func TestMultipleNamesAllUsed(t *testing.T) {
186
187 s := mkstate()
188 nn := s.nmi64("n")
189 nm := s.nmi64("m")
190 nne101 := bin(nn, ir.ONE, liti(101))
191 mlt2 := bin(nm, ir.OLT, liti(2))
192 nandand := typecheck.Expr(logical(nne101, ir.OANDAND, mlt2))
193
194
195 wantv := true
196 v := ShouldFoldIfNameConstant(nandand, []*ir.Name{nn, nm})
197 if v != wantv {
198 t.Errorf("wanted shouldfold(%v) %v, got %v", nandand, wantv, v)
199 }
200
201
202 wantv = false
203 v = ShouldFoldIfNameConstant(nne101, []*ir.Name{nn, nm})
204 if v != wantv {
205 t.Errorf("wanted shouldfold(%v) %v, got %v", nne101, wantv, v)
206 }
207
208
209 np := s.nmi64("p")
210 pne0 := bin(np, ir.ONE, liti(101))
211 noror := logical(nandand, ir.OOROR, pne0)
212 wantv = false
213 v = ShouldFoldIfNameConstant(noror, []*ir.Name{nn, nm})
214 if v != wantv {
215 t.Errorf("wanted shouldfold(%v) %v, got %v", noror, wantv, v)
216 }
217 }
218
View as plain text