OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits> | 5 #include <limits> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 #include "test/cctest/cctest.h" | 8 #include "test/cctest/cctest.h" |
9 #include "test/cctest/compiler/graph-builder-tester.h" | 9 #include "test/cctest/compiler/graph-builder-tester.h" |
10 | 10 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 Node* n = Parameter(0); | 81 Node* n = Parameter(0); |
82 Node* c = changer()->GetRepresentationFor(n, from, to); | 82 Node* c = changer()->GetRepresentationFor(n, from, to); |
83 CHECK_EQ(n, c); | 83 CHECK_EQ(n, c); |
84 } | 84 } |
85 }; | 85 }; |
86 } | 86 } |
87 } | 87 } |
88 } // namespace v8::internal::compiler | 88 } // namespace v8::internal::compiler |
89 | 89 |
90 | 90 |
91 // TODO(titzer): add kRepFloat32 when fully supported. | |
92 static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64, | 91 static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64, |
93 kRepFloat32, kRepFloat64, kRepTagged}; | 92 kRepFloat32, kRepFloat64, kRepTagged}; |
94 | 93 |
95 | 94 |
96 // TODO(titzer): lift this to ValueHelper | 95 // TODO(titzer): lift this to ValueHelper |
97 static const double double_inputs[] = { | 96 static const double double_inputs[] = { |
98 0.0, -0.0, 1.0, -1.0, 0.1, 1.4, -1.7, | 97 0.0, -0.0, 1.0, -1.0, 0.1, 1.4, -1.7, |
99 2, 5, 6, 982983, 888, -999.8, 3.1e7, | 98 2, 5, 6, 982983, 888, -999.8, 3.1e7, |
100 -2e66, 2.3e124, -12e73, V8_INFINITY, -V8_INFINITY}; | 99 -2e66, 2.3e124, -12e73, V8_INFINITY, -V8_INFINITY}; |
101 | 100 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 | 140 |
142 TEST(ToTagged_constant) { | 141 TEST(ToTagged_constant) { |
143 RepresentationChangerTester r; | 142 RepresentationChangerTester r; |
144 | 143 |
145 for (size_t i = 0; i < arraysize(double_inputs); i++) { | 144 for (size_t i = 0; i < arraysize(double_inputs); i++) { |
146 Node* n = r.jsgraph()->Float64Constant(double_inputs[i]); | 145 Node* n = r.jsgraph()->Float64Constant(double_inputs[i]); |
147 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepTagged); | 146 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepTagged); |
148 r.CheckNumberConstant(c, double_inputs[i]); | 147 r.CheckNumberConstant(c, double_inputs[i]); |
149 } | 148 } |
150 | 149 |
| 150 for (size_t i = 0; i < arraysize(double_inputs); i++) { |
| 151 volatile float fval = static_cast<float>(double_inputs[i]); |
| 152 Node* n = r.jsgraph()->Float32Constant(fval); |
| 153 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32, kRepTagged); |
| 154 r.CheckNumberConstant(c, fval); |
| 155 } |
| 156 |
151 for (size_t i = 0; i < arraysize(int32_inputs); i++) { | 157 for (size_t i = 0; i < arraysize(int32_inputs); i++) { |
152 Node* n = r.jsgraph()->Int32Constant(int32_inputs[i]); | 158 Node* n = r.jsgraph()->Int32Constant(int32_inputs[i]); |
153 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32, | 159 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32, |
154 kRepTagged); | 160 kRepTagged); |
155 r.CheckNumberConstant(c, static_cast<double>(int32_inputs[i])); | 161 r.CheckNumberConstant(c, static_cast<double>(int32_inputs[i])); |
156 } | 162 } |
157 | 163 |
158 for (size_t i = 0; i < arraysize(uint32_inputs); i++) { | 164 for (size_t i = 0; i < arraysize(uint32_inputs); i++) { |
159 Node* n = r.jsgraph()->Int32Constant(uint32_inputs[i]); | 165 Node* n = r.jsgraph()->Int32Constant(uint32_inputs[i]); |
160 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32, | 166 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32, |
161 kRepTagged); | 167 kRepTagged); |
162 r.CheckNumberConstant(c, static_cast<double>(uint32_inputs[i])); | 168 r.CheckNumberConstant(c, static_cast<double>(uint32_inputs[i])); |
163 } | 169 } |
164 } | 170 } |
165 | 171 |
166 | 172 |
167 static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from, | 173 static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from, |
168 MachineTypeUnion to) { | 174 MachineTypeUnion to) { |
169 RepresentationChangerTester r; | 175 RepresentationChangerTester r; |
170 | 176 |
171 Node* n = r.Parameter(); | 177 Node* n = r.Parameter(); |
172 Node* c = r.changer()->GetRepresentationFor(n, from, to); | 178 Node* c = r.changer()->GetRepresentationFor(n, from, to); |
173 | 179 |
174 CHECK_NE(c, n); | 180 CHECK_NE(c, n); |
175 CHECK_EQ(expected, c->opcode()); | 181 CHECK_EQ(expected, c->opcode()); |
176 CHECK_EQ(n, c->InputAt(0)); | 182 CHECK_EQ(n, c->InputAt(0)); |
177 } | 183 } |
178 | 184 |
179 | 185 |
| 186 static void CheckTwoChanges(IrOpcode::Value expected2, |
| 187 IrOpcode::Value expected1, MachineTypeUnion from, |
| 188 MachineTypeUnion to) { |
| 189 RepresentationChangerTester r; |
| 190 |
| 191 Node* n = r.Parameter(); |
| 192 Node* c1 = r.changer()->GetRepresentationFor(n, from, to); |
| 193 |
| 194 CHECK_NE(c1, n); |
| 195 CHECK_EQ(expected1, c1->opcode()); |
| 196 Node* c2 = c1->InputAt(0); |
| 197 CHECK_NE(c2, n); |
| 198 CHECK_EQ(expected2, c2->opcode()); |
| 199 CHECK_EQ(n, c2->InputAt(0)); |
| 200 } |
| 201 |
| 202 |
180 TEST(SingleChanges) { | 203 TEST(SingleChanges) { |
181 CheckChange(IrOpcode::kChangeBoolToBit, kRepTagged, kRepBit); | 204 CheckChange(IrOpcode::kChangeBoolToBit, kRepTagged, kRepBit); |
182 CheckChange(IrOpcode::kChangeBitToBool, kRepBit, kRepTagged); | 205 CheckChange(IrOpcode::kChangeBitToBool, kRepBit, kRepTagged); |
183 | 206 |
184 CheckChange(IrOpcode::kChangeInt32ToTagged, kRepWord32 | kTypeInt32, | 207 CheckChange(IrOpcode::kChangeInt32ToTagged, kRepWord32 | kTypeInt32, |
185 kRepTagged); | 208 kRepTagged); |
186 CheckChange(IrOpcode::kChangeUint32ToTagged, kRepWord32 | kTypeUint32, | 209 CheckChange(IrOpcode::kChangeUint32ToTagged, kRepWord32 | kTypeUint32, |
187 kRepTagged); | 210 kRepTagged); |
188 CheckChange(IrOpcode::kChangeFloat64ToTagged, kRepFloat64, kRepTagged); | 211 CheckChange(IrOpcode::kChangeFloat64ToTagged, kRepFloat64, kRepTagged); |
189 | 212 |
190 CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged | kTypeInt32, | 213 CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged | kTypeInt32, |
191 kRepWord32); | 214 kRepWord32); |
192 CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged | kTypeUint32, | 215 CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged | kTypeUint32, |
193 kRepWord32); | 216 kRepWord32); |
194 CheckChange(IrOpcode::kChangeTaggedToFloat64, kRepTagged, kRepFloat64); | 217 CheckChange(IrOpcode::kChangeTaggedToFloat64, kRepTagged, kRepFloat64); |
195 | 218 |
196 // Int32,Uint32 <-> Float64 are actually machine conversions. | 219 // Int32,Uint32 <-> Float64 are actually machine conversions. |
197 CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32 | kTypeInt32, | 220 CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32 | kTypeInt32, |
198 kRepFloat64); | 221 kRepFloat64); |
199 CheckChange(IrOpcode::kChangeUint32ToFloat64, kRepWord32 | kTypeUint32, | 222 CheckChange(IrOpcode::kChangeUint32ToFloat64, kRepWord32 | kTypeUint32, |
200 kRepFloat64); | 223 kRepFloat64); |
201 CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64 | kTypeInt32, | 224 CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64 | kTypeInt32, |
202 kRepWord32); | 225 kRepWord32); |
203 CheckChange(IrOpcode::kChangeFloat64ToUint32, kRepFloat64 | kTypeUint32, | 226 CheckChange(IrOpcode::kChangeFloat64ToUint32, kRepFloat64 | kTypeUint32, |
204 kRepWord32); | 227 kRepWord32); |
| 228 |
| 229 // Int32,Uint32 <-> Float32 require two changes. |
| 230 CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64, |
| 231 IrOpcode::kTruncateFloat64ToFloat32, kRepWord32 | kTypeInt32, |
| 232 kRepFloat32); |
| 233 CheckTwoChanges(IrOpcode::kChangeUint32ToFloat64, |
| 234 IrOpcode::kTruncateFloat64ToFloat32, kRepWord32 | kTypeUint32, |
| 235 kRepFloat32); |
| 236 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, |
| 237 IrOpcode::kChangeFloat64ToInt32, kRepFloat32 | kTypeInt32, |
| 238 kRepWord32); |
| 239 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, |
| 240 IrOpcode::kChangeFloat64ToUint32, kRepFloat32 | kTypeUint32, |
| 241 kRepWord32); |
| 242 |
| 243 // Float32 <-> Tagged require two changes. |
| 244 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, |
| 245 IrOpcode::kChangeFloat64ToTagged, kRepFloat32, kRepTagged); |
| 246 CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64, |
| 247 IrOpcode::kTruncateFloat64ToFloat32, kRepTagged, kRepFloat32); |
205 } | 248 } |
206 | 249 |
207 | 250 |
| 251 // TODO(titzer): test constant folding of changes between int/float |
| 252 |
| 253 |
208 TEST(SignednessInWord32) { | 254 TEST(SignednessInWord32) { |
209 RepresentationChangerTester r; | 255 RepresentationChangerTester r; |
210 | 256 |
211 // TODO(titzer): assume that uses of a word32 without a sign mean kTypeInt32. | 257 // TODO(titzer): assume that uses of a word32 without a sign mean kTypeInt32. |
212 CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged, | 258 CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged, |
213 kRepWord32 | kTypeInt32); | 259 kRepWord32 | kTypeInt32); |
214 CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged, | 260 CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged, |
215 kRepWord32 | kTypeUint32); | 261 kRepWord32 | kTypeUint32); |
216 CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32, kRepFloat64); | 262 CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32, kRepFloat64); |
217 CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64, kRepWord32); | 263 CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64, kRepWord32); |
| 264 |
| 265 CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64, |
| 266 IrOpcode::kTruncateFloat64ToFloat32, kRepWord32, kRepFloat32); |
| 267 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, |
| 268 IrOpcode::kChangeFloat64ToInt32, kRepFloat32, kRepWord32); |
218 } | 269 } |
219 | 270 |
220 | 271 |
221 TEST(Nops) { | 272 TEST(Nops) { |
222 RepresentationChangerTester r; | 273 RepresentationChangerTester r; |
223 | 274 |
224 // X -> X is always a nop for any single representation X. | 275 // X -> X is always a nop for any single representation X. |
225 for (size_t i = 0; i < arraysize(all_reps); i++) { | 276 for (size_t i = 0; i < arraysize(all_reps); i++) { |
226 r.CheckNop(all_reps[i], all_reps[i]); | 277 r.CheckNop(all_reps[i], all_reps[i]); |
227 } | 278 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 r.CheckTypeError(kRepWord32 | kTypeUint32, kRepWord64); | 340 r.CheckTypeError(kRepWord32 | kTypeUint32, kRepWord64); |
290 | 341 |
291 for (size_t i = 0; i < arraysize(all_reps); i++) { | 342 for (size_t i = 0; i < arraysize(all_reps); i++) { |
292 for (size_t j = 0; j < arraysize(all_reps); j++) { | 343 for (size_t j = 0; j < arraysize(all_reps); j++) { |
293 if (i == j) continue; | 344 if (i == j) continue; |
294 // Only a single from representation is allowed. | 345 // Only a single from representation is allowed. |
295 r.CheckTypeError(all_reps[i] | all_reps[j], kRepTagged); | 346 r.CheckTypeError(all_reps[i] | all_reps[j], kRepTagged); |
296 } | 347 } |
297 } | 348 } |
298 } | 349 } |
OLD | NEW |