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 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 jsgraph.Int32Constant(1)); | 737 jsgraph.Int32Constant(1)); |
738 } else if (type & kRepWord64) { | 738 } else if (type & kRepWord64) { |
739 return graph()->NewNode(machine()->Int64Add(), Int64Constant(1), | 739 return graph()->NewNode(machine()->Int64Add(), Int64Constant(1), |
740 Int64Constant(1)); | 740 Int64Constant(1)); |
741 } else { | 741 } else { |
742 CHECK(type & kRepTagged); | 742 CHECK(type & kRepTagged); |
743 return p0; | 743 return p0; |
744 } | 744 } |
745 } | 745 } |
746 | 746 |
| 747 Node* ExampleWithTypeAndRep(Type* type, MachineType mach_type) { |
| 748 FieldAccess access = {kUntaggedBase, 0, Handle<Name>::null(), type, |
| 749 mach_type}; |
| 750 // TODO(titzer): using loads here just to force the representation is ugly. |
| 751 Node* node = graph()->NewNode(simplified()->LoadField(access), |
| 752 jsgraph.IntPtrConstant(0), graph()->start(), |
| 753 graph()->start()); |
| 754 NodeProperties::SetBounds(node, Bounds(type)); |
| 755 return node; |
| 756 } |
| 757 |
747 Node* Use(Node* node, MachineType type) { | 758 Node* Use(Node* node, MachineType type) { |
748 if (type & kTypeInt32) { | 759 if (type & kTypeInt32) { |
749 return graph()->NewNode(machine()->Int32LessThan(), node, | 760 return graph()->NewNode(machine()->Int32LessThan(), node, |
750 jsgraph.Int32Constant(1)); | 761 jsgraph.Int32Constant(1)); |
751 } else if (type & kTypeUint32) { | 762 } else if (type & kTypeUint32) { |
752 return graph()->NewNode(machine()->Uint32LessThan(), node, | 763 return graph()->NewNode(machine()->Uint32LessThan(), node, |
753 jsgraph.Int32Constant(1)); | 764 jsgraph.Int32Constant(1)); |
754 } else if (type & kRepFloat64) { | 765 } else if (type & kRepFloat64) { |
755 return graph()->NewNode(machine()->Float64Add(), node, | 766 return graph()->NewNode(machine()->Float64Add(), node, |
756 jsgraph.Float64Constant(1)); | 767 jsgraph.Float64Constant(1)); |
757 } else if (type & kRepWord64) { | 768 } else if (type & kRepWord64) { |
758 return graph()->NewNode(machine()->Int64LessThan(), node, | 769 return graph()->NewNode(machine()->Int64LessThan(), node, |
759 Int64Constant(1)); | 770 Int64Constant(1)); |
| 771 } else if (type & kRepWord32) { |
| 772 return graph()->NewNode(machine()->Word32Equal(), node, |
| 773 jsgraph.Int32Constant(1)); |
760 } else { | 774 } else { |
761 return graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), node, | 775 return graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), node, |
762 jsgraph.TrueConstant()); | 776 jsgraph.TrueConstant()); |
763 } | 777 } |
764 } | 778 } |
765 | 779 |
766 Node* Branch(Node* cond) { | 780 Node* Branch(Node* cond) { |
767 Node* br = graph()->NewNode(common()->Branch(), cond, start); | 781 Node* br = graph()->NewNode(common()->Branch(), cond, start); |
768 Node* tb = graph()->NewNode(common()->IfTrue(), br); | 782 Node* tb = graph()->NewNode(common()->IfTrue(), br); |
769 Node* fb = graph()->NewNode(common()->IfFalse(), br); | 783 Node* fb = graph()->NewNode(common()->IfFalse(), br); |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 Node* use = t.Use(trunc, kTypeInt32); | 1067 Node* use = t.Use(trunc, kTypeInt32); |
1054 t.Return(use); | 1068 t.Return(use); |
1055 t.Lower(); | 1069 t.Lower(); |
1056 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0)); | 1070 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0)); |
1057 } | 1071 } |
1058 | 1072 |
1059 | 1073 |
1060 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { | 1074 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { |
1061 // NumberToInt32(x: kRepFloat64) used as kMachInt32 | 1075 // NumberToInt32(x: kRepFloat64) used as kMachInt32 |
1062 TestingGraph t(Type::Number()); | 1076 TestingGraph t(Type::Number()); |
1063 Node* p0 = t.ExampleWithOutput(kMachFloat64); | 1077 Node* p0 = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64); |
1064 // TODO(titzer): run the typer here, or attach machine type to param. | |
1065 NodeProperties::SetBounds(p0, Bounds(Type::Number())); | |
1066 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0); | 1078 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0); |
1067 Node* use = t.Use(trunc, kMachInt32); | 1079 Node* use = t.Use(trunc, kMachInt32); |
1068 t.Return(use); | 1080 t.Return(use); |
1069 t.Lower(); | 1081 t.Lower(); |
1070 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); | 1082 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); |
1071 } | 1083 } |
1072 | 1084 |
1073 | 1085 |
1074 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) { | 1086 TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) { |
1075 // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachInt32 | 1087 // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachInt32 |
1076 TestingGraph t(Type::Number()); | 1088 TestingGraph t(Type::Number()); |
1077 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0); | 1089 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0); |
1078 Node* use = t.Use(trunc, kMachInt32); | 1090 Node* use = t.Use(trunc, kMachInt32); |
1079 t.Return(use); | 1091 t.Return(use); |
1080 t.Lower(); | 1092 t.Lower(); |
1081 Node* node = use->InputAt(0); | 1093 Node* node = use->InputAt(0); |
1082 CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode()); | 1094 CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode()); |
1083 Node* of = node->InputAt(0); | 1095 Node* of = node->InputAt(0); |
1084 CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode()); | 1096 CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode()); |
1085 CHECK_EQ(t.p0, of->InputAt(0)); | 1097 CHECK_EQ(t.p0, of->InputAt(0)); |
1086 } | 1098 } |
1087 | 1099 |
1088 | 1100 |
1089 TEST(LowerNumberToInt32_to_ChangeFloat64ToTagged) { | |
1090 // TODO(titzer): NumberToInt32(x: kRepFloat64 | kTypeInt32) used as kRepTagged | |
1091 } | |
1092 | |
1093 | |
1094 TEST(LowerNumberToInt32_to_ChangeFloat64ToInt32) { | |
1095 // TODO(titzer): NumberToInt32(x: kRepFloat64 | kTypeInt32) used as kRepWord32 | |
1096 // | kTypeInt32 | |
1097 } | |
1098 | |
1099 | |
1100 TEST(LowerNumberToUint32_to_nop) { | 1101 TEST(LowerNumberToUint32_to_nop) { |
1101 // NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepTagged | 1102 // NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepTagged |
1102 TestingGraph t(Type::Unsigned32()); | 1103 TestingGraph t(Type::Unsigned32()); |
1103 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0); | 1104 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0); |
1104 Node* use = t.Use(trunc, kRepTagged); | 1105 Node* use = t.Use(trunc, kRepTagged); |
1105 t.Return(use); | 1106 t.Return(use); |
1106 t.Lower(); | 1107 t.Lower(); |
1107 CHECK_EQ(t.p0, use->InputAt(0)); | 1108 CHECK_EQ(t.p0, use->InputAt(0)); |
1108 } | 1109 } |
1109 | 1110 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 t.Return(use); | 1153 t.Return(use); |
1153 t.Lower(); | 1154 t.Lower(); |
1154 Node* node = use->InputAt(0); | 1155 Node* node = use->InputAt(0); |
1155 CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode()); | 1156 CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode()); |
1156 Node* of = node->InputAt(0); | 1157 Node* of = node->InputAt(0); |
1157 CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode()); | 1158 CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode()); |
1158 CHECK_EQ(t.p0, of->InputAt(0)); | 1159 CHECK_EQ(t.p0, of->InputAt(0)); |
1159 } | 1160 } |
1160 | 1161 |
1161 | 1162 |
1162 TEST(LowerNumberToUint32_to_ChangeFloat64ToTagged) { | 1163 TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) { |
1163 // TODO(titzer): NumberToUint32(x: kRepFloat64 | kTypeUint32) used as | 1164 // NumberToUint32(x: kRepFloat64) used as kRepWord32 |
1164 // kRepTagged | 1165 TestingGraph t(Type::Unsigned32()); |
| 1166 Node* input = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64); |
| 1167 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), input); |
| 1168 Node* use = t.Use(trunc, kRepWord32); |
| 1169 t.Return(use); |
| 1170 t.Lower(); |
| 1171 CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0)); |
1165 } | 1172 } |
1166 | 1173 |
1167 | 1174 |
1168 TEST(LowerNumberToUint32_to_ChangeFloat64ToUint32) { | 1175 TEST(LowerNumberToUI32_of_Float64_used_as_word32) { |
1169 // TODO(titzer): NumberToUint32(x: kRepFloat64 | kTypeUint32) used as | 1176 // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as |
1170 // kRepWord32 | 1177 // kType(Int,Uint)32 | kRepWord32 |
| 1178 Type* types[] = {Type::Signed32(), Type::Unsigned32()}; |
| 1179 MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone}; |
| 1180 |
| 1181 for (int i = 0; i < 2; i++) { |
| 1182 for (int u = 0; u < 3; u++) { |
| 1183 TestingGraph t(types[i]); |
| 1184 Node* input = t.ExampleWithTypeAndRep( |
| 1185 types[i], static_cast<MachineType>(kRepFloat64 | mach[i])); |
| 1186 const Operator* op = i == 0 ? t.simplified()->NumberToInt32() |
| 1187 : t.simplified()->NumberToUint32(); |
| 1188 Node* trunc = t.graph()->NewNode(op, input); |
| 1189 Node* use = t.Use(trunc, static_cast<MachineType>(kRepWord32 | mach[u])); |
| 1190 t.Return(use); |
| 1191 t.Lower(); |
| 1192 IrOpcode::Value opcode = i == 0 ? IrOpcode::kChangeFloat64ToInt32 |
| 1193 : IrOpcode::kChangeFloat64ToUint32; |
| 1194 CheckChangeOf(opcode, input, use->InputAt(0)); |
| 1195 } |
| 1196 } |
1171 } | 1197 } |
1172 | 1198 |
1173 | 1199 |
1174 TEST(LowerNumberToUint32_to_TruncateFloat64ToUint32) { | 1200 TEST(LowerNumberToUI32_of_Float64_used_as_tagged) { |
1175 // TODO(titzer): NumberToUint32(x: kRepFloat64) used as kRepWord32 | 1201 // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as |
| 1202 // kType(Int,Uint)32 | kRepTagged |
| 1203 Type* types[] = {Type::Signed32(), Type::Unsigned32(), Type::Any()}; |
| 1204 MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone}; |
| 1205 |
| 1206 for (int i = 0; i < 2; i++) { |
| 1207 for (int u = 0; u < 3; u++) { |
| 1208 TestingGraph t(types[i]); |
| 1209 Node* input = t.ExampleWithTypeAndRep( |
| 1210 types[i], static_cast<MachineType>(kRepFloat64 | mach[i])); |
| 1211 const Operator* op = i == 0 ? t.simplified()->NumberToInt32() |
| 1212 : t.simplified()->NumberToUint32(); |
| 1213 Node* trunc = t.graph()->NewNode(op, input); |
| 1214 // TODO(titzer): we use the store here to force the representation. |
| 1215 FieldAccess access = {kTaggedBase, 0, Handle<Name>(), types[u], |
| 1216 static_cast<MachineType>(mach[u] | kRepTagged)}; |
| 1217 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, |
| 1218 trunc, t.start, t.start); |
| 1219 t.Effect(store); |
| 1220 t.Lower(); |
| 1221 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, input, store->InputAt(2)); |
| 1222 } |
| 1223 } |
1176 } | 1224 } |
1177 | 1225 |
1178 | 1226 |
1179 TEST(LowerReferenceEqual_to_wordeq) { | 1227 TEST(LowerReferenceEqual_to_wordeq) { |
1180 TestingGraph t(Type::Any(), Type::Any()); | 1228 TestingGraph t(Type::Any(), Type::Any()); |
1181 IrOpcode::Value opcode = | 1229 IrOpcode::Value opcode = |
1182 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode()); | 1230 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode()); |
1183 t.CheckLoweringBinop(opcode, t.simplified()->ReferenceEqual(Type::Any())); | 1231 t.CheckLoweringBinop(opcode, t.simplified()->ReferenceEqual(Type::Any())); |
1184 } | 1232 } |
1185 | 1233 |
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1998 Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z); | 2046 Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z); |
1999 NodeProperties::SetBounds(phi, phi_bounds); | 2047 NodeProperties::SetBounds(phi, phi_bounds); |
2000 | 2048 |
2001 Node* use = t.Use(phi, d.use); | 2049 Node* use = t.Use(phi, d.use); |
2002 t.Return(use); | 2050 t.Return(use); |
2003 t.Lower(); | 2051 t.Lower(); |
2004 | 2052 |
2005 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); | 2053 CHECK_EQ(d.expected, OpParameter<MachineType>(phi)); |
2006 } | 2054 } |
2007 } | 2055 } |
OLD | NEW |