| 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 |