| 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/graph-reducer.h" | 10 #include "src/compiler/graph-reducer.h" |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 jsgraph.Int32Constant(1)); | 738 jsgraph.Int32Constant(1)); |
| 739 } else if (type & kRepWord64) { | 739 } else if (type & kRepWord64) { |
| 740 return graph()->NewNode(machine()->Int64Add(), Int64Constant(1), | 740 return graph()->NewNode(machine()->Int64Add(), Int64Constant(1), |
| 741 Int64Constant(1)); | 741 Int64Constant(1)); |
| 742 } else { | 742 } else { |
| 743 CHECK(type & kRepTagged); | 743 CHECK(type & kRepTagged); |
| 744 return p0; | 744 return p0; |
| 745 } | 745 } |
| 746 } | 746 } |
| 747 | 747 |
| 748 Node* ExampleWithTypeAndRep(Type* type, MachineType mach_type) { | |
| 749 FieldAccess access = {kUntaggedBase, 0, Handle<Name>::null(), type, | |
| 750 mach_type}; | |
| 751 // TODO(titzer): using loads here just to force the representation is ugly. | |
| 752 Node* node = graph()->NewNode(simplified()->LoadField(access), | |
| 753 jsgraph.IntPtrConstant(0), graph()->start(), | |
| 754 graph()->start()); | |
| 755 NodeProperties::SetBounds(node, Bounds(type)); | |
| 756 return node; | |
| 757 } | |
| 758 | |
| 759 Node* Use(Node* node, MachineType type) { | 748 Node* Use(Node* node, MachineType type) { |
| 760 if (type & kTypeInt32) { | 749 if (type & kTypeInt32) { |
| 761 return graph()->NewNode(machine()->Int32LessThan(), node, | 750 return graph()->NewNode(machine()->Int32LessThan(), node, |
| 762 jsgraph.Int32Constant(1)); | 751 jsgraph.Int32Constant(1)); |
| 763 } else if (type & kTypeUint32) { | 752 } else if (type & kTypeUint32) { |
| 764 return graph()->NewNode(machine()->Uint32LessThan(), node, | 753 return graph()->NewNode(machine()->Uint32LessThan(), node, |
| 765 jsgraph.Int32Constant(1)); | 754 jsgraph.Int32Constant(1)); |
| 766 } else if (type & kRepFloat64) { | 755 } else if (type & kRepFloat64) { |
| 767 return graph()->NewNode(machine()->Float64Add(), node, | 756 return graph()->NewNode(machine()->Float64Add(), node, |
| 768 jsgraph.Float64Constant(1)); | 757 jsgraph.Float64Constant(1)); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 Node* use = t.Use(trunc, kTypeInt32); | 1051 Node* use = t.Use(trunc, kTypeInt32); |
| 1063 t.Return(use); | 1052 t.Return(use); |
| 1064 t.Lower(); | 1053 t.Lower(); |
| 1065 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0)); | 1054 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0)); |
| 1066 } | 1055 } |
| 1067 | 1056 |
| 1068 | 1057 |
| 1069 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { | 1058 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { |
| 1070 // NumberToInt32(x: kRepFloat64) used as kMachInt32 | 1059 // NumberToInt32(x: kRepFloat64) used as kMachInt32 |
| 1071 TestingGraph t(Type::Number()); | 1060 TestingGraph t(Type::Number()); |
| 1072 Node* p0 = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64); | 1061 Node* p0 = t.ExampleWithOutput(kMachFloat64); |
| 1073 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0); | 1062 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0); |
| 1074 Node* use = t.Use(trunc, kMachInt32); | 1063 Node* use = t.Use(trunc, kMachInt32); |
| 1075 t.Return(use); | 1064 t.Return(use); |
| 1076 t.Lower(); | 1065 t.Lower(); |
| 1077 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); | 1066 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); |
| 1078 } | 1067 } |
| 1079 | 1068 |
| 1080 | 1069 |
| 1081 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) { | 1070 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) { |
| 1082 // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachInt32 | 1071 // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachInt32 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1151 CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode()); | 1140 CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode()); |
| 1152 Node* of = node->InputAt(0); | 1141 Node* of = node->InputAt(0); |
| 1153 CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode()); | 1142 CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode()); |
| 1154 CHECK_EQ(t.p0, of->InputAt(0)); | 1143 CHECK_EQ(t.p0, of->InputAt(0)); |
| 1155 } | 1144 } |
| 1156 | 1145 |
| 1157 | 1146 |
| 1158 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) { | 1147 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) { |
| 1159 // NumberToUint32(x: kRepFloat64) used as kRepWord32 | 1148 // NumberToUint32(x: kRepFloat64) used as kRepWord32 |
| 1160 TestingGraph t(Type::Unsigned32()); | 1149 TestingGraph t(Type::Unsigned32()); |
| 1161 Node* input = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64); | 1150 Node* input = t.ExampleWithOutput(kMachFloat64); |
| 1162 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), input); | 1151 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), input); |
| 1163 Node* use = t.Use(trunc, kRepWord32); | 1152 Node* use = t.Use(trunc, kRepWord32); |
| 1164 t.Return(use); | 1153 t.Return(use); |
| 1165 t.Lower(); | 1154 t.Lower(); |
| 1166 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0)); | 1155 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0)); |
| 1167 } | 1156 } |
| 1168 | 1157 |
| 1169 | 1158 |
| 1170 TEST(LowerNumberToUI32_of_Float64_used_as_word32) { | |
| 1171 // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as | |
| 1172 // kType(Int,Uint)32 | kRepWord32 | |
| 1173 Type* types[] = {Type::Signed32(), Type::Unsigned32()}; | |
| 1174 MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone}; | |
| 1175 | |
| 1176 for (int i = 0; i < 2; i++) { | |
| 1177 for (int u = 0; u < 3; u++) { | |
| 1178 TestingGraph t(types[i]); | |
| 1179 Node* input = t.ExampleWithTypeAndRep( | |
| 1180 types[i], static_cast<MachineType>(kRepFloat64 | mach[i])); | |
| 1181 const Operator* op = i == 0 ? t.simplified()->NumberToInt32() | |
| 1182 : t.simplified()->NumberToUint32(); | |
| 1183 Node* trunc = t.graph()->NewNode(op, input); | |
| 1184 Node* use = t.Use(trunc, static_cast<MachineType>(kRepWord32 | mach[u])); | |
| 1185 t.Return(use); | |
| 1186 t.Lower(); | |
| 1187 IrOpcode::Value opcode = i == 0 ? IrOpcode::kChangeFloat64ToInt32 | |
| 1188 : IrOpcode::kChangeFloat64ToUint32; | |
| 1189 CheckChangeOf(opcode, input, use->InputAt(0)); | |
| 1190 } | |
| 1191 } | |
| 1192 } | |
| 1193 | |
| 1194 | |
| 1195 TEST(LowerNumberToUI32_of_Float64_used_as_tagged) { | |
| 1196 // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as | |
| 1197 // kType(Int,Uint)32 | kRepTagged | |
| 1198 Type* types[] = {Type::Signed32(), Type::Unsigned32(), Type::Any()}; | |
| 1199 MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone}; | |
| 1200 | |
| 1201 for (int i = 0; i < 2; i++) { | |
| 1202 for (int u = 0; u < 3; u++) { | |
| 1203 TestingGraph t(types[i]); | |
| 1204 Node* input = t.ExampleWithTypeAndRep( | |
| 1205 types[i], static_cast<MachineType>(kRepFloat64 | mach[i])); | |
| 1206 const Operator* op = i == 0 ? t.simplified()->NumberToInt32() | |
| 1207 : t.simplified()->NumberToUint32(); | |
| 1208 Node* trunc = t.graph()->NewNode(op, input); | |
| 1209 // TODO(titzer): we use the store here to force the representation. | |
| 1210 FieldAccess access = {kTaggedBase, 0, Handle<Name>(), types[u], | |
| 1211 static_cast<MachineType>(mach[u] | kRepTagged)}; | |
| 1212 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, | |
| 1213 trunc, t.start, t.start); | |
| 1214 t.Effect(store); | |
| 1215 t.Lower(); | |
| 1216 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, input, store->InputAt(2)); | |
| 1217 } | |
| 1218 } | |
| 1219 } | |
| 1220 | |
| 1221 | |
| 1222 TEST(LowerReferenceEqual_to_wordeq) { | 1159 TEST(LowerReferenceEqual_to_wordeq) { |
| 1223 TestingGraph t(Type::Any(), Type::Any()); | 1160 TestingGraph t(Type::Any(), Type::Any()); |
| 1224 IrOpcode::Value opcode = | 1161 IrOpcode::Value opcode = |
| 1225 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode()); | 1162 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode()); |
| 1226 t.CheckLoweringBinop(opcode, t.simplified()->ReferenceEqual(Type::Any())); | 1163 t.CheckLoweringBinop(opcode, t.simplified()->ReferenceEqual(Type::Any())); |
| 1227 } | 1164 } |
| 1228 | 1165 |
| 1229 | 1166 |
| 1230 TEST(LowerStringOps_to_call_and_compare) { | 1167 TEST(LowerStringOps_to_call_and_compare) { |
| 1231 // These tests need linkage for the calls. | 1168 // These tests need linkage for the calls. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 Int32BinopMatcher shl(mindex.left().node()); | 1327 Int32BinopMatcher shl(mindex.left().node()); |
| 1391 CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode()); | 1328 CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode()); |
| 1392 CHECK(shl.right().Is(element_size_shift)); | 1329 CHECK(shl.right().Is(element_size_shift)); |
| 1393 return shl.left().node(); | 1330 return shl.left().node(); |
| 1394 } else { | 1331 } else { |
| 1395 return mindex.left().node(); | 1332 return mindex.left().node(); |
| 1396 } | 1333 } |
| 1397 } | 1334 } |
| 1398 | 1335 |
| 1399 | 1336 |
| 1400 const MachineType kMachineReps[] = {kRepBit, kMachInt8, kMachInt16, | 1337 const MachineType kMachineReps[] = {kMachInt8, kMachInt16, kMachInt32, |
| 1401 kMachInt32, kMachInt64, kMachFloat64, | 1338 kMachUint32, kMachInt64, kMachFloat64, |
| 1402 kMachAnyTagged}; | 1339 kMachAnyTagged}; |
| 1403 | 1340 |
| 1404 } // namespace | 1341 } // namespace |
| 1405 | 1342 |
| 1406 | 1343 |
| 1407 TEST(LowerLoadField_to_load) { | 1344 TEST(LowerLoadField_to_load) { |
| 1408 TestingGraph t(Type::Any(), Type::Signed32()); | 1345 TestingGraph t(Type::Any(), Type::Signed32()); |
| 1409 | 1346 |
| 1410 for (size_t i = 0; i < arraysize(kMachineReps); i++) { | 1347 for (size_t i = 0; i < arraysize(kMachineReps); i++) { |
| 1411 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | 1348 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2047 Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z); | 1984 Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z); |
| 2048 NodeProperties::SetBounds(phi, phi_bounds); | 1985 NodeProperties::SetBounds(phi, phi_bounds); |
| 2049 | 1986 |
| 2050 Node* use = t.Use(phi, d.use); | 1987 Node* use = t.Use(phi, d.use); |
| 2051 t.Return(use); | 1988 t.Return(use); |
| 2052 t.Lower(); | 1989 t.Lower(); |
| 2053 | 1990 |
| 2054 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); | 1991 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); |
| 2055 } | 1992 } |
| 2056 } | 1993 } |
| OLD | NEW |