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 "src/compiler/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties-inl.h" | 7 #include "src/compiler/node-properties-inl.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 } else { // store [%base + %index], %|#value | 154 } else { // store [%base + %index], %|#value |
155 Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL, | 155 Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL, |
156 g.UseRegister(base), g.UseRegister(index), val); | 156 g.UseRegister(base), g.UseRegister(index), val); |
157 } | 157 } |
158 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] | 158 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] |
159 } | 159 } |
160 | 160 |
161 | 161 |
162 // Shared routine for multiple binary operations. | 162 // Shared routine for multiple binary operations. |
163 static void VisitBinop(InstructionSelector* selector, Node* node, | 163 static void VisitBinop(InstructionSelector* selector, Node* node, |
164 ArchOpcode opcode) { | 164 InstructionCode opcode, FlagsContinuation* cont) { |
165 IA32OperandGenerator g(selector); | 165 IA32OperandGenerator g(selector); |
166 Int32BinopMatcher m(node); | 166 Int32BinopMatcher m(node); |
167 // TODO(turbofan): match complex addressing modes. | 167 InstructionOperand* inputs[4]; |
168 // TODO(turbofan): if commutative, pick the non-live-in operand as the left as | |
169 // this might be the last use and therefore its register can be reused. | |
170 if (g.CanBeImmediate(m.right().node())) { | |
171 selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(m.left().node()), | |
172 g.UseImmediate(m.right().node())); | |
173 } else { | |
174 selector->Emit(opcode, g.DefineSameAsFirst(node), | |
175 g.UseRegister(m.left().node()), g.Use(m.right().node())); | |
176 } | |
177 } | |
178 | |
179 | |
180 static void VisitBinopWithOverflow(InstructionSelector* selector, Node* node, | |
181 InstructionCode opcode) { | |
182 IA32OperandGenerator g(selector); | |
183 Int32BinopMatcher m(node); | |
184 InstructionOperand* inputs[2]; | |
185 size_t input_count = 0; | 168 size_t input_count = 0; |
186 InstructionOperand* outputs[2]; | 169 InstructionOperand* outputs[2]; |
187 size_t output_count = 0; | 170 size_t output_count = 0; |
188 | 171 |
189 // TODO(turbofan): match complex addressing modes. | 172 // TODO(turbofan): match complex addressing modes. |
190 // TODO(turbofan): if commutative, pick the non-live-in operand as the left as | 173 // TODO(turbofan): if commutative, pick the non-live-in operand as the left as |
191 // this might be the last use and therefore its register can be reused. | 174 // this might be the last use and therefore its register can be reused. |
192 if (g.CanBeImmediate(m.right().node())) { | 175 if (g.CanBeImmediate(m.right().node())) { |
193 inputs[input_count++] = g.Use(m.left().node()); | 176 inputs[input_count++] = g.Use(m.left().node()); |
194 inputs[input_count++] = g.UseImmediate(m.right().node()); | 177 inputs[input_count++] = g.UseImmediate(m.right().node()); |
195 } else { | 178 } else { |
196 inputs[input_count++] = g.UseRegister(m.left().node()); | 179 inputs[input_count++] = g.UseRegister(m.left().node()); |
197 inputs[input_count++] = g.Use(m.right().node()); | 180 inputs[input_count++] = g.Use(m.right().node()); |
198 } | 181 } |
199 | 182 |
200 // Define outputs depending on the projections. | 183 if (cont->IsBranch()) { |
201 Node* projections[2]; | 184 inputs[input_count++] = g.Label(cont->true_block()); |
202 node->CollectProjections(ARRAY_SIZE(projections), projections); | 185 inputs[input_count++] = g.Label(cont->false_block()); |
203 if (projections[0]) { | |
204 outputs[output_count++] = g.DefineSameAsFirst(projections[0]); | |
205 } | 186 } |
206 if (projections[1]) { | 187 |
207 opcode |= FlagsModeField::encode(kFlags_set); | 188 outputs[output_count++] = g.DefineSameAsFirst(node); |
208 opcode |= FlagsConditionField::encode(kOverflow); | 189 if (cont->IsSet()) { |
209 // TODO(turbofan): Use byte register here. | 190 // TODO(turbofan): Use byte register here. |
210 outputs[output_count++] = | 191 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
211 (projections[0] ? g.DefineAsRegister(projections[1]) | |
212 : g.DefineSameAsFirst(projections[1])); | |
213 } | 192 } |
214 | 193 |
215 ASSERT_NE(0, input_count); | 194 ASSERT_NE(0, input_count); |
216 ASSERT_NE(0, output_count); | 195 ASSERT_NE(0, output_count); |
217 ASSERT_GE(ARRAY_SIZE(inputs), input_count); | 196 ASSERT_GE(ARRAY_SIZE(inputs), input_count); |
218 ASSERT_GE(ARRAY_SIZE(outputs), output_count); | 197 ASSERT_GE(ARRAY_SIZE(outputs), output_count); |
219 | 198 |
220 selector->Emit(opcode, output_count, outputs, input_count, inputs); | 199 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
| 200 outputs, input_count, inputs); |
| 201 if (cont->IsBranch()) instr->MarkAsControl(); |
221 } | 202 } |
222 | 203 |
223 | 204 |
| 205 // Shared routine for multiple binary operations. |
| 206 static void VisitBinop(InstructionSelector* selector, Node* node, |
| 207 InstructionCode opcode) { |
| 208 FlagsContinuation cont; |
| 209 VisitBinop(selector, node, opcode, &cont); |
| 210 } |
| 211 |
| 212 |
224 void InstructionSelector::VisitWord32And(Node* node) { | 213 void InstructionSelector::VisitWord32And(Node* node) { |
225 VisitBinop(this, node, kIA32And); | 214 VisitBinop(this, node, kIA32And); |
226 } | 215 } |
227 | 216 |
228 | 217 |
229 void InstructionSelector::VisitWord32Or(Node* node) { | 218 void InstructionSelector::VisitWord32Or(Node* node) { |
230 VisitBinop(this, node, kIA32Or); | 219 VisitBinop(this, node, kIA32Or); |
231 } | 220 } |
232 | 221 |
233 | 222 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 void InstructionSelector::VisitWord32Sar(Node* node) { | 269 void InstructionSelector::VisitWord32Sar(Node* node) { |
281 VisitShift(this, node, kIA32Sar); | 270 VisitShift(this, node, kIA32Sar); |
282 } | 271 } |
283 | 272 |
284 | 273 |
285 void InstructionSelector::VisitInt32Add(Node* node) { | 274 void InstructionSelector::VisitInt32Add(Node* node) { |
286 VisitBinop(this, node, kIA32Add); | 275 VisitBinop(this, node, kIA32Add); |
287 } | 276 } |
288 | 277 |
289 | 278 |
290 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | |
291 VisitBinopWithOverflow(this, node, kIA32Add); | |
292 } | |
293 | |
294 | |
295 void InstructionSelector::VisitInt32Sub(Node* node) { | 279 void InstructionSelector::VisitInt32Sub(Node* node) { |
296 IA32OperandGenerator g(this); | 280 IA32OperandGenerator g(this); |
297 Int32BinopMatcher m(node); | 281 Int32BinopMatcher m(node); |
298 if (m.left().Is(0)) { | 282 if (m.left().Is(0)) { |
299 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); | 283 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); |
300 } else { | 284 } else { |
301 VisitBinop(this, node, kIA32Sub); | 285 VisitBinop(this, node, kIA32Sub); |
302 } | 286 } |
303 } | 287 } |
304 | 288 |
305 | 289 |
306 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | |
307 VisitBinopWithOverflow(this, node, kIA32Sub); | |
308 } | |
309 | |
310 | |
311 void InstructionSelector::VisitInt32Mul(Node* node) { | 290 void InstructionSelector::VisitInt32Mul(Node* node) { |
312 IA32OperandGenerator g(this); | 291 IA32OperandGenerator g(this); |
313 Node* left = node->InputAt(0); | 292 Node* left = node->InputAt(0); |
314 Node* right = node->InputAt(1); | 293 Node* right = node->InputAt(1); |
315 if (g.CanBeImmediate(right)) { | 294 if (g.CanBeImmediate(right)) { |
316 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), | 295 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), |
317 g.UseImmediate(right)); | 296 g.UseImmediate(right)); |
318 } else if (g.CanBeImmediate(left)) { | 297 } else if (g.CanBeImmediate(left)) { |
319 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(right), | 298 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(right), |
320 g.UseImmediate(left)); | 299 g.UseImmediate(left)); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 | 410 |
432 void InstructionSelector::VisitFloat64Mod(Node* node) { | 411 void InstructionSelector::VisitFloat64Mod(Node* node) { |
433 IA32OperandGenerator g(this); | 412 IA32OperandGenerator g(this); |
434 InstructionOperand* temps[] = {g.TempRegister(eax)}; | 413 InstructionOperand* temps[] = {g.TempRegister(eax)}; |
435 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), | 414 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), |
436 g.UseDoubleRegister(node->InputAt(0)), | 415 g.UseDoubleRegister(node->InputAt(0)), |
437 g.UseDoubleRegister(node->InputAt(1)), 1, temps); | 416 g.UseDoubleRegister(node->InputAt(1)), 1, temps); |
438 } | 417 } |
439 | 418 |
440 | 419 |
| 420 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, |
| 421 FlagsContinuation* cont) { |
| 422 VisitBinop(this, node, kIA32Add, cont); |
| 423 } |
| 424 |
| 425 |
| 426 void InstructionSelector::VisitInt32SubWithOverflow(Node* node, |
| 427 FlagsContinuation* cont) { |
| 428 VisitBinop(this, node, kIA32Sub, cont); |
| 429 } |
| 430 |
| 431 |
441 // Shared routine for multiple compare operations. | 432 // Shared routine for multiple compare operations. |
442 static inline void VisitCompare(InstructionSelector* selector, | 433 static inline void VisitCompare(InstructionSelector* selector, |
443 InstructionCode opcode, | 434 InstructionCode opcode, |
444 InstructionOperand* left, | 435 InstructionOperand* left, |
445 InstructionOperand* right, | 436 InstructionOperand* right, |
446 FlagsContinuation* cont) { | 437 FlagsContinuation* cont) { |
447 IA32OperandGenerator g(selector); | 438 IA32OperandGenerator g(selector); |
448 if (cont->IsBranch()) { | 439 if (cont->IsBranch()) { |
449 selector->Emit(cont->Encode(opcode), NULL, left, right, | 440 selector->Emit(cont->Encode(opcode), NULL, left, right, |
450 g.Label(cont->true_block()), | 441 g.Label(cont->true_block()), |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 if (descriptor->kind() == CallDescriptor::kCallAddress && | 551 if (descriptor->kind() == CallDescriptor::kCallAddress && |
561 buffer.pushed_count > 0) { | 552 buffer.pushed_count > 0) { |
562 ASSERT(deoptimization == NULL && continuation == NULL); | 553 ASSERT(deoptimization == NULL && continuation == NULL); |
563 Emit(kPopStack | MiscField::encode(buffer.pushed_count), NULL); | 554 Emit(kPopStack | MiscField::encode(buffer.pushed_count), NULL); |
564 } | 555 } |
565 } | 556 } |
566 | 557 |
567 } // namespace compiler | 558 } // namespace compiler |
568 } // namespace internal | 559 } // namespace internal |
569 } // namespace v8 | 560 } // namespace v8 |
OLD | NEW |