Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/compiler/int64-lowering.h" | |
| 6 #include "src/compiler/common-operator.h" | |
| 7 #include "src/compiler/linkage.h" | |
| 8 #include "src/compiler/machine-operator.h" | |
| 9 #include "src/compiler/node.h" | |
| 10 | |
| 11 #include "src/compiler/node-properties.h" | |
| 12 | |
| 13 #include "src/signature.h" | |
| 14 | |
| 15 #include "src/wasm/wasm-module.h" | |
| 16 | |
| 17 #include "test/unittests/compiler/graph-unittest.h" | |
| 18 #include "test/unittests/compiler/node-test-utils.h" | |
| 19 | |
| 20 namespace v8 { | |
| 21 namespace internal { | |
| 22 namespace compiler { | |
| 23 | |
| 24 class Int64LoweringTest : public GraphTest { | |
| 25 public: | |
| 26 Int64LoweringTest() : GraphTest(), machine_(zone()) { | |
| 27 value_[0] = 0x1234567890abcdef; | |
| 28 value_[1] = 0x1edcba098765432f; | |
| 29 value_[2] = 0x1133557799886644; | |
| 30 } | |
| 31 | |
| 32 MachineOperatorBuilder* machine() { return &machine_; } | |
| 33 | |
| 34 void LowerGraph(Node* node, Signature<MachineRepresentation>* signature) { | |
| 35 Node* ret = graph()->NewNode(common()->Return(), node, graph()->start(), | |
| 36 graph()->start()); | |
| 37 NodeProperties::MergeControlToEnd(graph(), common(), ret); | |
| 38 | |
| 39 Int64Lowering lowering(graph(), machine(), common(), zone(), signature); | |
| 40 lowering.LowerGraph(); | |
| 41 } | |
| 42 | |
| 43 void LowerGraph(Node* node, MachineRepresentation return_type, | |
| 44 MachineRepresentation rep = MachineRepresentation::kWord32, | |
| 45 int num_params = 0) { | |
| 46 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, | |
| 47 num_params); | |
| 48 sig_builder.AddReturn(return_type); | |
| 49 for (int i = 0; i < num_params; i++) { | |
| 50 sig_builder.AddParam(rep); | |
| 51 } | |
| 52 LowerGraph(node, sig_builder.Build()); | |
| 53 } | |
| 54 | |
| 55 void CompareCallDescriptors(const CallDescriptor* lhs, | |
| 56 const CallDescriptor* rhs) { | |
| 57 EXPECT_THAT(lhs->CalleeSavedFPRegisters(), rhs->CalleeSavedFPRegisters()); | |
| 58 EXPECT_THAT(lhs->CalleeSavedRegisters(), rhs->CalleeSavedRegisters()); | |
| 59 EXPECT_THAT(lhs->FrameStateCount(), rhs->FrameStateCount()); | |
| 60 EXPECT_THAT(lhs->InputCount(), rhs->InputCount()); | |
| 61 for (size_t i = 0; i < lhs->InputCount(); i++) { | |
| 62 EXPECT_THAT(lhs->GetInputLocation(i), rhs->GetInputLocation(i)); | |
| 63 EXPECT_THAT(lhs->GetInputType(i), rhs->GetInputType(i)); | |
| 64 } | |
| 65 EXPECT_THAT(lhs->ReturnCount(), rhs->ReturnCount()); | |
| 66 for (size_t i = 0; i < lhs->ReturnCount(); i++) { | |
| 67 EXPECT_THAT(lhs->GetReturnLocation(i), rhs->GetReturnLocation(i)); | |
| 68 EXPECT_THAT(lhs->GetReturnType(i), rhs->GetReturnType(i)); | |
| 69 } | |
| 70 EXPECT_THAT(lhs->flags(), rhs->flags()); | |
| 71 EXPECT_THAT(lhs->kind(), rhs->kind()); | |
| 72 } | |
| 73 | |
| 74 int64_t value(int i) { return value_[i]; } | |
| 75 | |
| 76 int32_t low_word_value(int i) { | |
| 77 return static_cast<int32_t>(value_[i] & 0xffffffff); | |
| 78 } | |
| 79 | |
| 80 int32_t high_word_value(int i) { | |
| 81 return static_cast<int32_t>(value_[i] >> 32); | |
| 82 } | |
| 83 | |
| 84 private: | |
| 85 MachineOperatorBuilder machine_; | |
| 86 int64_t value_[3]; | |
| 87 }; | |
| 88 | |
| 89 TEST_F(Int64LoweringTest, Int64Constant) { | |
| 90 if (4 != kPointerSize) return; | |
| 91 | |
| 92 LowerGraph(Int64Constant(value(0)), MachineRepresentation::kWord64); | |
| 93 EXPECT_THAT(graph()->end()->InputAt(1), | |
| 94 IsReturn2(IsInt32Constant(low_word_value(0)), | |
| 95 IsInt32Constant(high_word_value(0)), start(), start())); | |
| 96 } | |
| 97 | |
| 98 TEST_F(Int64LoweringTest, Int64Load) { | |
| 99 if (4 != kPointerSize) return; | |
| 100 | |
| 101 int32_t base = 0x1234; | |
| 102 int32_t index = 0x5678; | |
| 103 | |
| 104 LowerGraph(graph()->NewNode(machine()->Load(MachineType::Int64()), | |
| 105 Int32Constant(base), Int32Constant(index), | |
| 106 start(), start()), | |
| 107 MachineRepresentation::kWord64); | |
| 108 | |
| 109 Matcher<Node*> high_word_load_matcher = | |
| 110 IsLoad(MachineType::Int32(), IsInt32Constant(base), | |
| 111 IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), start(), | |
| 112 start()); | |
| 113 | |
| 114 EXPECT_THAT( | |
| 115 graph()->end()->InputAt(1), | |
| 116 IsReturn2(IsLoad(MachineType::Int32(), IsInt32Constant(base), | |
| 117 IsInt32Constant(index), high_word_load_matcher, start()), | |
| 118 high_word_load_matcher, start(), start())); | |
| 119 } | |
| 120 | |
| 121 TEST_F(Int64LoweringTest, Int64Store) { | |
| 122 if (4 != kPointerSize) return; | |
| 123 | |
| 124 // We have to build the TF graph explicitly here because Store does not return | |
| 125 // a value. | |
| 126 | |
| 127 int32_t base = 1111; | |
| 128 int32_t index = 2222; | |
| 129 int32_t return_value = 0x5555; | |
| 130 | |
| 131 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0); | |
| 132 sig_builder.AddReturn(MachineRepresentation::kWord32); | |
| 133 | |
| 134 Node* store = graph()->NewNode( | |
| 135 machine()->Store(StoreRepresentation(MachineRepresentation::kWord64, | |
| 136 WriteBarrierKind::kNoWriteBarrier)), | |
| 137 Int32Constant(base), Int32Constant(index), Int64Constant(value(0)), | |
| 138 start(), start()); | |
| 139 | |
| 140 Node* ret = graph()->NewNode(common()->Return(), Int32Constant(return_value), | |
| 141 store, start()); | |
| 142 | |
| 143 NodeProperties::MergeControlToEnd(graph(), common(), ret); | |
| 144 | |
| 145 Int64Lowering lowering(graph(), machine(), common(), zone(), | |
| 146 sig_builder.Build()); | |
| 147 lowering.LowerGraph(); | |
| 148 | |
| 149 const StoreRepresentation rep(MachineRepresentation::kWord32, | |
| 150 kNoWriteBarrier); | |
| 151 | |
| 152 EXPECT_THAT( | |
| 153 graph()->end()->InputAt(1), | |
| 154 IsReturn( | |
| 155 IsInt32Constant(return_value), | |
| 156 IsStore( | |
| 157 rep, IsInt32Constant(base), IsInt32Constant(index), | |
| 158 IsInt32Constant(low_word_value(0)), | |
| 159 IsStore(rep, IsInt32Constant(base), | |
| 160 IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)), | |
| 161 IsInt32Constant(high_word_value(0)), start(), start()), | |
| 162 start()), | |
| 163 start())); | |
| 164 } | |
| 165 | |
| 166 TEST_F(Int64LoweringTest, Int64And) { | |
| 167 if (4 != kPointerSize) return; | |
| 168 | |
| 169 LowerGraph(graph()->NewNode(machine()->Word64And(), Int64Constant(value(0)), | |
| 170 Int64Constant(value(1))), | |
| 171 MachineRepresentation::kWord64); | |
| 172 EXPECT_THAT(graph()->end()->InputAt(1), | |
| 173 IsReturn2(IsWord32And(IsInt32Constant(low_word_value(0)), | |
| 174 IsInt32Constant(low_word_value(1))), | |
| 175 IsWord32And(IsInt32Constant(high_word_value(0)), | |
| 176 IsInt32Constant(high_word_value(1))), | |
| 177 start(), start())); | |
| 178 } | |
| 179 | |
| 180 TEST_F(Int64LoweringTest, TruncateInt64ToInt32) { | |
| 181 if (4 != kPointerSize) return; | |
| 182 | |
| 183 LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(), | |
| 184 Int64Constant(value(0))), | |
| 185 MachineRepresentation::kWord32); | |
| 186 EXPECT_THAT(graph()->end()->InputAt(1), | |
| 187 IsReturn(IsInt32Constant(low_word_value(0)), start(), start())); | |
| 188 } | |
| 189 | |
| 190 TEST_F(Int64LoweringTest, Parameter) { | |
| 191 if (4 != kPointerSize) return; | |
| 192 | |
| 193 LowerGraph(Parameter(0), MachineRepresentation::kWord64, | |
| 194 MachineRepresentation::kWord64, 1); | |
| 195 | |
| 196 EXPECT_THAT(graph()->end()->InputAt(1), | |
| 197 IsReturn2(IsParameter(0), IsParameter(1), start(), start())); | |
| 198 } | |
| 199 | |
| 200 TEST_F(Int64LoweringTest, Parameter2) { | |
| 201 if (4 != kPointerSize) return; | |
| 202 | |
| 203 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 5); | |
| 204 sig_builder.AddReturn(MachineRepresentation::kWord32); | |
| 205 | |
| 206 sig_builder.AddParam(MachineRepresentation::kWord32); | |
| 207 sig_builder.AddParam(MachineRepresentation::kWord64); | |
| 208 sig_builder.AddParam(MachineRepresentation::kFloat64); | |
| 209 sig_builder.AddParam(MachineRepresentation::kWord64); | |
| 210 sig_builder.AddParam(MachineRepresentation::kWord32); | |
| 211 | |
| 212 int start_parameter = start()->op()->ValueOutputCount(); | |
| 213 LowerGraph(Parameter(4), sig_builder.Build()); | |
| 214 | |
| 215 EXPECT_THAT(graph()->end()->InputAt(1), | |
| 216 IsReturn(IsParameter(6), start(), start())); | |
| 217 // The parameter of the start node should increase by 2, because we lowered | |
| 218 // two parameter nodes. | |
| 219 EXPECT_THAT(start()->op()->ValueOutputCount(), start_parameter + 2); | |
| 220 } | |
| 221 | |
| 222 TEST_F(Int64LoweringTest, CallI64Return) { | |
| 223 if (4 != kPointerSize) return; | |
| 224 | |
| 225 int32_t function = 0x9999; | |
| 226 | |
| 227 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0); | |
| 228 sig_builder.AddReturn(MachineRepresentation::kWord64); | |
| 229 | |
| 230 compiler::CallDescriptor* desc = | |
| 231 wasm::ModuleEnv::GetWasmCallDescriptor(zone(), sig_builder.Build()); | |
| 232 | |
| 233 LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function), | |
| 234 start(), start()), | |
| 235 MachineRepresentation::kWord64); | |
| 236 | |
| 237 Matcher<Node*> call_matcher = | |
| 238 IsCall(testing::_, IsInt32Constant(function), start(), start()); | |
| 239 | |
| 240 EXPECT_THAT(graph()->end()->InputAt(1), | |
| 241 IsReturn2(IsProjection(0, call_matcher), | |
|
Michael Starzinger
2016/02/23 14:24:03
If you wanted to make sure that both projections a
ahaas
2016/02/23 14:48:56
Done.
| |
| 242 IsProjection(1, call_matcher), start(), start())); | |
| 243 | |
| 244 CompareCallDescriptors( | |
| 245 OpParameter<const CallDescriptor*>( | |
| 246 graph()->end()->InputAt(1)->InputAt(0)->InputAt(0)), | |
| 247 wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc)); | |
| 248 } | |
| 249 | |
| 250 TEST_F(Int64LoweringTest, CallI64Parameter) { | |
| 251 if (4 != kPointerSize) return; | |
| 252 | |
| 253 int32_t function = 0x9999; | |
| 254 | |
| 255 Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 3); | |
| 256 sig_builder.AddReturn(MachineRepresentation::kWord32); | |
| 257 sig_builder.AddParam(MachineRepresentation::kWord64); | |
| 258 sig_builder.AddParam(MachineRepresentation::kWord32); | |
| 259 sig_builder.AddParam(MachineRepresentation::kWord64); | |
| 260 | |
| 261 compiler::CallDescriptor* desc = | |
| 262 wasm::ModuleEnv::GetWasmCallDescriptor(zone(), sig_builder.Build()); | |
| 263 | |
| 264 LowerGraph(graph()->NewNode(common()->Call(desc), Int32Constant(function), | |
| 265 Int64Constant(value(0)), | |
| 266 Int32Constant(low_word_value(1)), | |
| 267 Int64Constant(value(2)), start(), start()), | |
| 268 MachineRepresentation::kWord32); | |
| 269 | |
| 270 EXPECT_THAT( | |
| 271 graph()->end()->InputAt(1), | |
| 272 IsReturn(IsCall(testing::_, IsInt32Constant(function), | |
| 273 IsInt32Constant(low_word_value(0)), | |
| 274 IsInt32Constant(high_word_value(0)), | |
| 275 IsInt32Constant(low_word_value(1)), | |
| 276 IsInt32Constant(low_word_value(2)), | |
| 277 IsInt32Constant(high_word_value(2)), start(), start()), | |
| 278 start(), start())); | |
| 279 | |
| 280 CompareCallDescriptors( | |
| 281 OpParameter<const CallDescriptor*>( | |
| 282 graph()->end()->InputAt(1)->InputAt(0)), | |
| 283 wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc)); | |
| 284 } | |
| 285 | |
| 286 } // namespace compiler | |
| 287 } // namespace internal | |
| 288 } // namespace v8 | |
| OLD | NEW |