| 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/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
| 8 #include "src/compiler/change-lowering.h" | 8 #include "src/compiler/change-lowering.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/generic-node-inl.h" | 10 #include "src/compiler/generic-node-inl.h" |
| (...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 t.machine()->Float64LessThan(), | 1317 t.machine()->Float64LessThan(), |
| 1318 t.machine()->Float64LessThanOrEqual()}; | 1318 t.machine()->Float64LessThanOrEqual()}; |
| 1319 | 1319 |
| 1320 for (size_t i = 0; i < arraysize(ops); i++) { | 1320 for (size_t i = 0; i < arraysize(ops); i++) { |
| 1321 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64, | 1321 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64, |
| 1322 IrOpcode::kChangeBitToBool); | 1322 IrOpcode::kChangeBitToBool); |
| 1323 } | 1323 } |
| 1324 } | 1324 } |
| 1325 | 1325 |
| 1326 | 1326 |
| 1327 namespace { |
| 1328 |
| 1327 void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) { | 1329 void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) { |
| 1328 Int32Matcher index = Int32Matcher(load_or_store->InputAt(1)); | 1330 IntPtrMatcher mindex(load_or_store->InputAt(1)); |
| 1329 CHECK(index.Is(access.offset - access.tag())); | 1331 CHECK(mindex.Is(access.offset - access.tag())); |
| 1330 } | 1332 } |
| 1331 | 1333 |
| 1332 | 1334 |
| 1333 Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) { | 1335 Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) { |
| 1334 Int32BinopMatcher index(load_or_store->InputAt(1)); | 1336 Node* index = load_or_store->InputAt(1); |
| 1335 CHECK_EQ(IrOpcode::kInt32Add, index.node()->opcode()); | 1337 if (kPointerSize == 8) { |
| 1336 CHECK(index.right().Is(access.header_size - access.tag())); | 1338 CHECK_EQ(IrOpcode::kChangeUint32ToUint64, index->opcode()); |
| 1339 index = index->InputAt(0); |
| 1340 } |
| 1337 | 1341 |
| 1338 int element_size = ElementSizeOf(access.machine_type); | 1342 Int32BinopMatcher mindex(index); |
| 1343 CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode()); |
| 1344 CHECK(mindex.right().Is(access.header_size - access.tag())); |
| 1339 | 1345 |
| 1340 if (element_size != 1) { | 1346 const int element_size_shift = ElementSizeLog2Of(access.machine_type); |
| 1341 Int32BinopMatcher mul(index.left().node()); | 1347 if (element_size_shift) { |
| 1342 CHECK_EQ(IrOpcode::kInt32Mul, mul.node()->opcode()); | 1348 Int32BinopMatcher shl(mindex.left().node()); |
| 1343 CHECK(mul.right().Is(element_size)); | 1349 CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode()); |
| 1344 return mul.left().node(); | 1350 CHECK(shl.right().Is(element_size_shift)); |
| 1351 return shl.left().node(); |
| 1345 } else { | 1352 } else { |
| 1346 return index.left().node(); | 1353 return mindex.left().node(); |
| 1347 } | 1354 } |
| 1348 } | 1355 } |
| 1349 | 1356 |
| 1350 | 1357 |
| 1351 static const MachineType machine_reps[] = { | 1358 const MachineType kMachineReps[] = {kRepBit, kMachInt8, kMachInt16, |
| 1352 kRepBit, kMachInt8, kMachInt16, kMachInt32, | 1359 kMachInt32, kMachInt64, kMachFloat64, |
| 1353 kMachInt64, kMachFloat64, kMachAnyTagged}; | 1360 kMachAnyTagged}; |
| 1361 |
| 1362 } // namespace |
| 1354 | 1363 |
| 1355 | 1364 |
| 1356 TEST(LowerLoadField_to_load) { | 1365 TEST(LowerLoadField_to_load) { |
| 1357 TestingGraph t(Type::Any(), Type::Signed32()); | 1366 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1358 | 1367 |
| 1359 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1368 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1360 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1369 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1361 Handle<Name>::null(), Type::Any(), machine_reps[i]}; | 1370 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; |
| 1362 | 1371 |
| 1363 Node* load = | 1372 Node* load = |
| 1364 t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); | 1373 t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); |
| 1365 Node* use = t.Use(load, machine_reps[i]); | 1374 Node* use = t.Use(load, kMachineReps[i]); |
| 1366 t.Return(use); | 1375 t.Return(use); |
| 1367 t.Lower(); | 1376 t.Lower(); |
| 1368 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1377 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1369 CHECK_EQ(t.p0, load->InputAt(0)); | 1378 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1370 CheckFieldAccessArithmetic(access, load); | 1379 CheckFieldAccessArithmetic(access, load); |
| 1371 | 1380 |
| 1372 MachineType rep = OpParameter<MachineType>(load); | 1381 MachineType rep = OpParameter<MachineType>(load); |
| 1373 CHECK_EQ(machine_reps[i], rep); | 1382 CHECK_EQ(kMachineReps[i], rep); |
| 1374 } | 1383 } |
| 1375 } | 1384 } |
| 1376 | 1385 |
| 1377 | 1386 |
| 1378 TEST(LowerStoreField_to_store) { | 1387 TEST(LowerStoreField_to_store) { |
| 1379 TestingGraph t(Type::Any(), Type::Signed32()); | 1388 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1380 | 1389 |
| 1381 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1390 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1382 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1391 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| 1383 Handle<Name>::null(), Type::Any(), machine_reps[i]}; | 1392 Handle<Name>::null(), Type::Any(), kMachineReps[i]}; |
| 1384 | 1393 |
| 1385 | 1394 |
| 1386 Node* val = t.ExampleWithOutput(machine_reps[i]); | 1395 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
| 1387 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | 1396 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
| 1388 val, t.start, t.start); | 1397 val, t.start, t.start); |
| 1389 t.Effect(store); | 1398 t.Effect(store); |
| 1390 t.Lower(); | 1399 t.Lower(); |
| 1391 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1400 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1392 CHECK_EQ(val, store->InputAt(2)); | 1401 CHECK_EQ(val, store->InputAt(2)); |
| 1393 CheckFieldAccessArithmetic(access, store); | 1402 CheckFieldAccessArithmetic(access, store); |
| 1394 | 1403 |
| 1395 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1404 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
| 1396 if (machine_reps[i] & kRepTagged) { | 1405 if (kMachineReps[i] & kRepTagged) { |
| 1397 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1406 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
| 1398 } | 1407 } |
| 1399 CHECK_EQ(machine_reps[i], rep.machine_type()); | 1408 CHECK_EQ(kMachineReps[i], rep.machine_type()); |
| 1400 } | 1409 } |
| 1401 } | 1410 } |
| 1402 | 1411 |
| 1403 | 1412 |
| 1404 TEST(LowerLoadElement_to_load) { | 1413 TEST(LowerLoadElement_to_load) { |
| 1405 TestingGraph t(Type::Any(), Type::Signed32()); | 1414 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1406 | 1415 |
| 1407 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1416 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1408 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1417 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
| 1409 FixedArrayBase::kHeaderSize, Type::Any(), | 1418 FixedArrayBase::kHeaderSize, Type::Any(), |
| 1410 machine_reps[i]}; | 1419 kMachineReps[i]}; |
| 1411 | 1420 |
| 1412 Node* load = | 1421 Node* load = |
| 1413 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, | 1422 t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0, t.p1, |
| 1414 t.jsgraph.Int32Constant(1024), t.start, t.start); | 1423 t.jsgraph.Int32Constant(1024), t.start, t.start); |
| 1415 Node* use = t.Use(load, machine_reps[i]); | 1424 Node* use = t.Use(load, kMachineReps[i]); |
| 1416 t.Return(use); | 1425 t.Return(use); |
| 1417 t.Lower(); | 1426 t.Lower(); |
| 1418 CHECK_EQ(IrOpcode::kLoad, load->opcode()); | 1427 CHECK_EQ(IrOpcode::kLoad, load->opcode()); |
| 1419 CHECK_EQ(t.p0, load->InputAt(0)); | 1428 CHECK_EQ(t.p0, load->InputAt(0)); |
| 1420 CheckElementAccessArithmetic(access, load); | 1429 CheckElementAccessArithmetic(access, load); |
| 1421 | 1430 |
| 1422 MachineType rep = OpParameter<MachineType>(load); | 1431 MachineType rep = OpParameter<MachineType>(load); |
| 1423 CHECK_EQ(machine_reps[i], rep); | 1432 CHECK_EQ(kMachineReps[i], rep); |
| 1424 } | 1433 } |
| 1425 } | 1434 } |
| 1426 | 1435 |
| 1427 | 1436 |
| 1428 TEST(LowerStoreElement_to_store) { | 1437 TEST(LowerStoreElement_to_store) { |
| 1429 TestingGraph t(Type::Any(), Type::Signed32()); | 1438 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1430 | 1439 |
| 1431 for (size_t i = 0; i < arraysize(machine_reps); i++) { | 1440 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1432 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1441 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
| 1433 FixedArrayBase::kHeaderSize, Type::Any(), | 1442 FixedArrayBase::kHeaderSize, Type::Any(), |
| 1434 machine_reps[i]}; | 1443 kMachineReps[i]}; |
| 1435 | 1444 |
| 1436 Node* val = t.ExampleWithOutput(machine_reps[i]); | 1445 Node* val = t.ExampleWithOutput(kMachineReps[i]); |
| 1437 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, | 1446 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, |
| 1438 t.p1, t.jsgraph.Int32Constant(1024), val, | 1447 t.p1, t.jsgraph.Int32Constant(1024), val, |
| 1439 t.start, t.start); | 1448 t.start, t.start); |
| 1440 t.Effect(store); | 1449 t.Effect(store); |
| 1441 t.Lower(); | 1450 t.Lower(); |
| 1442 CHECK_EQ(IrOpcode::kStore, store->opcode()); | 1451 CHECK_EQ(IrOpcode::kStore, store->opcode()); |
| 1443 CHECK_EQ(val, store->InputAt(2)); | 1452 CHECK_EQ(val, store->InputAt(2)); |
| 1444 CheckElementAccessArithmetic(access, store); | 1453 CheckElementAccessArithmetic(access, store); |
| 1445 | 1454 |
| 1446 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); | 1455 StoreRepresentation rep = OpParameter<StoreRepresentation>(store); |
| 1447 if (machine_reps[i] & kRepTagged) { | 1456 if (kMachineReps[i] & kRepTagged) { |
| 1448 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); | 1457 CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); |
| 1449 } | 1458 } |
| 1450 CHECK_EQ(machine_reps[i], rep.machine_type()); | 1459 CHECK_EQ(kMachineReps[i], rep.machine_type()); |
| 1451 } | 1460 } |
| 1452 } | 1461 } |
| 1453 | 1462 |
| 1454 | 1463 |
| 1455 TEST(InsertChangeForLoadElementIndex) { | 1464 TEST(InsertChangeForLoadElementIndex) { |
| 1456 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => | 1465 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) => |
| 1457 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) | 1466 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k)) |
| 1458 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); | 1467 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any()); |
| 1459 ElementAccess access = {kNoBoundsCheck, kTaggedBase, | 1468 ElementAccess access = {kNoBoundsCheck, kTaggedBase, |
| 1460 FixedArrayBase::kHeaderSize, Type::Any(), | 1469 FixedArrayBase::kHeaderSize, Type::Any(), |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1920 for (size_t i = 0; i < arraysize(constants); i++) { | 1929 for (size_t i = 0; i < arraysize(constants); i++) { |
| 1921 TestingGraph t(Type::Signed32()); | 1930 TestingGraph t(Type::Signed32()); |
| 1922 Node* k = t.jsgraph.Constant(constants[i]); | 1931 Node* k = t.jsgraph.Constant(constants[i]); |
| 1923 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); | 1932 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); |
| 1924 t.Return(mod); | 1933 t.Return(mod); |
| 1925 t.Lower(); | 1934 t.Lower(); |
| 1926 | 1935 |
| 1927 CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); // Pesky -0 behavior. | 1936 CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); // Pesky -0 behavior. |
| 1928 } | 1937 } |
| 1929 } | 1938 } |
| OLD | NEW |