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 |