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 20 matching lines...) Expand all Loading... |
31 // Constants in new space cannot be used as immediates in V8 because | 31 // Constants in new space cannot be used as immediates in V8 because |
32 // the GC does not scan code objects when collecting the new generation. | 32 // the GC does not scan code objects when collecting the new generation. |
33 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); | 33 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); |
34 return !isolate()->heap()->InNewSpace(*value.handle()); | 34 return !isolate()->heap()->InNewSpace(*value.handle()); |
35 } | 35 } |
36 default: | 36 default: |
37 return false; | 37 return false; |
38 } | 38 } |
39 } | 39 } |
40 | 40 |
| 41 AddressingMode GenerateMemoryOperandInputs(Node* index, int scale, Node* base, |
| 42 Node* displacement_node, |
| 43 InstructionOperand* inputs[], |
| 44 size_t* input_count) { |
| 45 AddressingMode mode = kMode_MRI; |
| 46 int32_t displacement = (displacement_node == NULL) |
| 47 ? 0 |
| 48 : OpParameter<int32_t>(displacement_node); |
| 49 if (base != NULL) { |
| 50 if (base->opcode() == IrOpcode::kInt32Constant) { |
| 51 displacement += OpParameter<int32_t>(base); |
| 52 base = NULL; |
| 53 } |
| 54 } |
| 55 if (base != NULL) { |
| 56 inputs[(*input_count)++] = UseRegister(base); |
| 57 if (index != NULL) { |
| 58 DCHECK(scale >= 0 && scale <= 3); |
| 59 inputs[(*input_count)++] = UseRegister(index); |
| 60 if (displacement != 0) { |
| 61 inputs[(*input_count)++] = TempImmediate(displacement); |
| 62 static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I, |
| 63 kMode_MR4I, kMode_MR8I}; |
| 64 mode = kMRnI_modes[scale]; |
| 65 } else { |
| 66 static const AddressingMode kMRn_modes[] = {kMode_MR1, kMode_MR2, |
| 67 kMode_MR4, kMode_MR8}; |
| 68 mode = kMRn_modes[scale]; |
| 69 } |
| 70 } else { |
| 71 if (displacement == 0) { |
| 72 mode = kMode_MR; |
| 73 } else { |
| 74 inputs[(*input_count)++] = TempImmediate(displacement); |
| 75 mode = kMode_MRI; |
| 76 } |
| 77 } |
| 78 } else { |
| 79 DCHECK(scale >= 0 && scale <= 3); |
| 80 if (index != NULL) { |
| 81 inputs[(*input_count)++] = UseRegister(index); |
| 82 if (displacement != 0) { |
| 83 inputs[(*input_count)++] = TempImmediate(displacement); |
| 84 static const AddressingMode kMnI_modes[] = {kMode_MRI, kMode_M2I, |
| 85 kMode_M4I, kMode_M8I}; |
| 86 mode = kMnI_modes[scale]; |
| 87 } else { |
| 88 static const AddressingMode kMn_modes[] = {kMode_MR, kMode_M2, |
| 89 kMode_M4, kMode_M8}; |
| 90 mode = kMn_modes[scale]; |
| 91 } |
| 92 } else { |
| 93 inputs[(*input_count)++] = TempImmediate(displacement); |
| 94 return kMode_MI; |
| 95 } |
| 96 } |
| 97 return mode; |
| 98 } |
| 99 |
| 100 AddressingMode GetEffectiveAddressMemoryOperand(Node* node, |
| 101 InstructionOperand* inputs[], |
| 102 size_t* input_count) { |
| 103 BaseWithIndexAndDisplacement32Matcher m(node, true); |
| 104 DCHECK(m.matches()); |
| 105 if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) { |
| 106 return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(), |
| 107 m.displacement(), inputs, input_count); |
| 108 } else { |
| 109 inputs[(*input_count)++] = UseRegister(node->InputAt(0)); |
| 110 inputs[(*input_count)++] = UseRegister(node->InputAt(1)); |
| 111 return kMode_MR1; |
| 112 } |
| 113 } |
| 114 |
41 bool CanBeBetterLeftOperand(Node* node) const { | 115 bool CanBeBetterLeftOperand(Node* node) const { |
42 return !selector()->IsLive(node); | 116 return !selector()->IsLive(node); |
43 } | 117 } |
44 }; | 118 }; |
45 | 119 |
46 | 120 |
47 // Get the AddressingMode of scale factor N from the AddressingMode of scale | |
48 // factor 1. | |
49 static AddressingMode AdjustAddressingMode(AddressingMode base_mode, | |
50 int power) { | |
51 DCHECK(0 <= power && power < 4); | |
52 return static_cast<AddressingMode>(static_cast<int>(base_mode) + power); | |
53 } | |
54 | |
55 | |
56 // Fairly intel-specify node matcher used for matching scale factors in | |
57 // addressing modes. | |
58 // Matches nodes of form [x * N] for N in {1,2,4,8} | |
59 class ScaleFactorMatcher : public NodeMatcher { | |
60 public: | |
61 static const int kMatchedFactors[4]; | |
62 | |
63 explicit ScaleFactorMatcher(Node* node); | |
64 | |
65 bool Matches() const { return left_ != NULL; } | |
66 int Power() const { | |
67 DCHECK(Matches()); | |
68 return power_; | |
69 } | |
70 Node* Left() const { | |
71 DCHECK(Matches()); | |
72 return left_; | |
73 } | |
74 | |
75 private: | |
76 Node* left_; | |
77 int power_; | |
78 }; | |
79 | |
80 | |
81 // Fairly intel-specify node matcher used for matching index and displacement | |
82 // operands in addressing modes. | |
83 // Matches nodes of form: | |
84 // [x * N] | |
85 // [x * N + K] | |
86 // [x + K] | |
87 // [x] -- fallback case | |
88 // for N in {1,2,4,8} and K int32_t | |
89 class IndexAndDisplacementMatcher : public NodeMatcher { | |
90 public: | |
91 explicit IndexAndDisplacementMatcher(Node* node); | |
92 | |
93 Node* index_node() const { return index_node_; } | |
94 int displacement() const { return displacement_; } | |
95 int power() const { return power_; } | |
96 | |
97 private: | |
98 Node* index_node_; | |
99 int displacement_; | |
100 int power_; | |
101 }; | |
102 | |
103 | |
104 // Fairly intel-specify node matcher used for matching multiplies that can be | |
105 // transformed to lea instructions. | |
106 // Matches nodes of form: | |
107 // [x * N] | |
108 // for N in {1,2,3,4,5,8,9} | |
109 class LeaMultiplyMatcher : public NodeMatcher { | |
110 public: | |
111 static const int kMatchedFactors[7]; | |
112 | |
113 explicit LeaMultiplyMatcher(Node* node); | |
114 | |
115 bool Matches() const { return left_ != NULL; } | |
116 int Power() const { | |
117 DCHECK(Matches()); | |
118 return power_; | |
119 } | |
120 Node* Left() const { | |
121 DCHECK(Matches()); | |
122 return left_; | |
123 } | |
124 // Displacement will be either 0 or 1. | |
125 int32_t Displacement() const { | |
126 DCHECK(Matches()); | |
127 return displacement_; | |
128 } | |
129 | |
130 private: | |
131 Node* left_; | |
132 int power_; | |
133 int displacement_; | |
134 }; | |
135 | |
136 | |
137 const int ScaleFactorMatcher::kMatchedFactors[] = {1, 2, 4, 8}; | |
138 | |
139 | |
140 ScaleFactorMatcher::ScaleFactorMatcher(Node* node) | |
141 : NodeMatcher(node), left_(NULL), power_(0) { | |
142 if (opcode() != IrOpcode::kInt32Mul) return; | |
143 // TODO(dcarney): should test 64 bit ints as well. | |
144 Int32BinopMatcher m(this->node()); | |
145 if (!m.right().HasValue()) return; | |
146 int32_t value = m.right().Value(); | |
147 switch (value) { | |
148 case 8: | |
149 power_++; // Fall through. | |
150 case 4: | |
151 power_++; // Fall through. | |
152 case 2: | |
153 power_++; // Fall through. | |
154 case 1: | |
155 break; | |
156 default: | |
157 return; | |
158 } | |
159 left_ = m.left().node(); | |
160 } | |
161 | |
162 | |
163 IndexAndDisplacementMatcher::IndexAndDisplacementMatcher(Node* node) | |
164 : NodeMatcher(node), index_node_(node), displacement_(0), power_(0) { | |
165 if (opcode() == IrOpcode::kInt32Add) { | |
166 Int32BinopMatcher m(this->node()); | |
167 if (m.right().HasValue()) { | |
168 displacement_ = m.right().Value(); | |
169 index_node_ = m.left().node(); | |
170 } | |
171 } | |
172 // Test scale factor. | |
173 ScaleFactorMatcher scale_matcher(index_node_); | |
174 if (scale_matcher.Matches()) { | |
175 index_node_ = scale_matcher.Left(); | |
176 power_ = scale_matcher.Power(); | |
177 } | |
178 } | |
179 | |
180 | |
181 const int LeaMultiplyMatcher::kMatchedFactors[7] = {1, 2, 3, 4, 5, 8, 9}; | |
182 | |
183 | |
184 LeaMultiplyMatcher::LeaMultiplyMatcher(Node* node) | |
185 : NodeMatcher(node), left_(NULL), power_(0), displacement_(0) { | |
186 if (opcode() != IrOpcode::kInt32Mul && opcode() != IrOpcode::kInt64Mul) { | |
187 return; | |
188 } | |
189 int64_t value; | |
190 Node* left = NULL; | |
191 { | |
192 Int32BinopMatcher m(this->node()); | |
193 if (m.right().HasValue()) { | |
194 value = m.right().Value(); | |
195 left = m.left().node(); | |
196 } else { | |
197 Int64BinopMatcher m(this->node()); | |
198 if (m.right().HasValue()) { | |
199 value = m.right().Value(); | |
200 left = m.left().node(); | |
201 } else { | |
202 return; | |
203 } | |
204 } | |
205 } | |
206 switch (value) { | |
207 case 9: | |
208 case 8: | |
209 power_++; // Fall through. | |
210 case 5: | |
211 case 4: | |
212 power_++; // Fall through. | |
213 case 3: | |
214 case 2: | |
215 power_++; // Fall through. | |
216 case 1: | |
217 break; | |
218 default: | |
219 return; | |
220 } | |
221 if (!base::bits::IsPowerOfTwo64(value)) { | |
222 displacement_ = 1; | |
223 } | |
224 left_ = left; | |
225 } | |
226 | |
227 | |
228 class AddressingModeMatcher { | |
229 public: | |
230 AddressingModeMatcher(IA32OperandGenerator* g, Node* base, Node* index) | |
231 : base_operand_(NULL), | |
232 index_operand_(NULL), | |
233 displacement_operand_(NULL), | |
234 mode_(kMode_None) { | |
235 Int32Matcher index_imm(index); | |
236 if (index_imm.HasValue()) { | |
237 int32_t displacement = index_imm.Value(); | |
238 // Compute base operand and fold base immediate into displacement. | |
239 Int32Matcher base_imm(base); | |
240 if (!base_imm.HasValue()) { | |
241 base_operand_ = g->UseRegister(base); | |
242 } else { | |
243 displacement += base_imm.Value(); | |
244 } | |
245 if (displacement != 0 || base_operand_ == NULL) { | |
246 displacement_operand_ = g->TempImmediate(displacement); | |
247 } | |
248 if (base_operand_ == NULL) { | |
249 mode_ = kMode_MI; | |
250 } else { | |
251 if (displacement == 0) { | |
252 mode_ = kMode_MR; | |
253 } else { | |
254 mode_ = kMode_MRI; | |
255 } | |
256 } | |
257 } else { | |
258 // Compute index and displacement. | |
259 IndexAndDisplacementMatcher matcher(index); | |
260 index_operand_ = g->UseRegister(matcher.index_node()); | |
261 int32_t displacement = matcher.displacement(); | |
262 // Compute base operand and fold base immediate into displacement. | |
263 Int32Matcher base_imm(base); | |
264 if (!base_imm.HasValue()) { | |
265 base_operand_ = g->UseRegister(base); | |
266 } else { | |
267 displacement += base_imm.Value(); | |
268 } | |
269 // Compute displacement operand. | |
270 if (displacement != 0) { | |
271 displacement_operand_ = g->TempImmediate(displacement); | |
272 } | |
273 // Compute mode with scale factor one. | |
274 if (base_operand_ == NULL) { | |
275 if (displacement_operand_ == NULL) { | |
276 mode_ = kMode_M1; | |
277 } else { | |
278 mode_ = kMode_M1I; | |
279 } | |
280 } else { | |
281 if (displacement_operand_ == NULL) { | |
282 mode_ = kMode_MR1; | |
283 } else { | |
284 mode_ = kMode_MR1I; | |
285 } | |
286 } | |
287 // Adjust mode to actual scale factor. | |
288 mode_ = AdjustAddressingMode(mode_, matcher.power()); | |
289 } | |
290 DCHECK_NE(kMode_None, mode_); | |
291 } | |
292 | |
293 size_t SetInputs(InstructionOperand** inputs) { | |
294 size_t input_count = 0; | |
295 // Compute inputs_ and input_count. | |
296 if (base_operand_ != NULL) { | |
297 inputs[input_count++] = base_operand_; | |
298 } | |
299 if (index_operand_ != NULL) { | |
300 inputs[input_count++] = index_operand_; | |
301 } | |
302 if (displacement_operand_ != NULL) { | |
303 inputs[input_count++] = displacement_operand_; | |
304 } | |
305 DCHECK_NE(input_count, 0); | |
306 return input_count; | |
307 } | |
308 | |
309 static const int kMaxInputCount = 3; | |
310 InstructionOperand* base_operand_; | |
311 InstructionOperand* index_operand_; | |
312 InstructionOperand* displacement_operand_; | |
313 AddressingMode mode_; | |
314 }; | |
315 | |
316 | |
317 static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 121 static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, |
318 Node* node) { | 122 Node* node) { |
319 IA32OperandGenerator g(selector); | 123 IA32OperandGenerator g(selector); |
320 selector->Emit(opcode, g.DefineAsRegister(node), | 124 selector->Emit(opcode, g.DefineAsRegister(node), |
321 g.UseRegister(node->InputAt(0))); | 125 g.UseRegister(node->InputAt(0))); |
322 } | 126 } |
323 | 127 |
324 | 128 |
325 void InstructionSelector::VisitLoad(Node* node) { | 129 void InstructionSelector::VisitLoad(Node* node) { |
326 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 130 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
327 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 131 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
328 Node* base = node->InputAt(0); | |
329 Node* index = node->InputAt(1); | |
330 | 132 |
331 ArchOpcode opcode; | 133 ArchOpcode opcode; |
332 // TODO(titzer): signed/unsigned small loads | 134 // TODO(titzer): signed/unsigned small loads |
333 switch (rep) { | 135 switch (rep) { |
334 case kRepFloat32: | 136 case kRepFloat32: |
335 opcode = kIA32Movss; | 137 opcode = kIA32Movss; |
336 break; | 138 break; |
337 case kRepFloat64: | 139 case kRepFloat64: |
338 opcode = kIA32Movsd; | 140 opcode = kIA32Movsd; |
339 break; | 141 break; |
340 case kRepBit: // Fall through. | 142 case kRepBit: // Fall through. |
341 case kRepWord8: | 143 case kRepWord8: |
342 opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; | 144 opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; |
343 break; | 145 break; |
344 case kRepWord16: | 146 case kRepWord16: |
345 opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; | 147 opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; |
346 break; | 148 break; |
347 case kRepTagged: // Fall through. | 149 case kRepTagged: // Fall through. |
348 case kRepWord32: | 150 case kRepWord32: |
349 opcode = kIA32Movl; | 151 opcode = kIA32Movl; |
350 break; | 152 break; |
351 default: | 153 default: |
352 UNREACHABLE(); | 154 UNREACHABLE(); |
353 return; | 155 return; |
354 } | 156 } |
355 | 157 |
356 IA32OperandGenerator g(this); | 158 IA32OperandGenerator g(this); |
357 AddressingModeMatcher matcher(&g, base, index); | 159 InstructionOperand* outputs[1]; |
358 InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_); | 160 outputs[0] = g.DefineAsRegister(node); |
359 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; | 161 InstructionOperand* inputs[3]; |
360 InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount]; | 162 size_t input_count = 0; |
361 size_t input_count = matcher.SetInputs(inputs); | 163 AddressingMode mode = |
| 164 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
| 165 InstructionCode code = opcode | AddressingModeField::encode(mode); |
362 Emit(code, 1, outputs, input_count, inputs); | 166 Emit(code, 1, outputs, input_count, inputs); |
363 } | 167 } |
364 | 168 |
365 | 169 |
366 void InstructionSelector::VisitStore(Node* node) { | 170 void InstructionSelector::VisitStore(Node* node) { |
367 IA32OperandGenerator g(this); | 171 IA32OperandGenerator g(this); |
368 Node* base = node->InputAt(0); | 172 Node* base = node->InputAt(0); |
369 Node* index = node->InputAt(1); | 173 Node* index = node->InputAt(1); |
370 Node* value = node->InputAt(2); | 174 Node* value = node->InputAt(2); |
371 | 175 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 | 214 |
411 InstructionOperand* val; | 215 InstructionOperand* val; |
412 if (g.CanBeImmediate(value)) { | 216 if (g.CanBeImmediate(value)) { |
413 val = g.UseImmediate(value); | 217 val = g.UseImmediate(value); |
414 } else if (rep == kRepWord8 || rep == kRepBit) { | 218 } else if (rep == kRepWord8 || rep == kRepBit) { |
415 val = g.UseByteRegister(value); | 219 val = g.UseByteRegister(value); |
416 } else { | 220 } else { |
417 val = g.UseRegister(value); | 221 val = g.UseRegister(value); |
418 } | 222 } |
419 | 223 |
420 AddressingModeMatcher matcher(&g, base, index); | 224 InstructionOperand* inputs[4]; |
421 InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_); | 225 size_t input_count = 0; |
422 InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount + 1]; | 226 AddressingMode mode = |
423 size_t input_count = matcher.SetInputs(inputs); | 227 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
| 228 InstructionCode code = opcode | AddressingModeField::encode(mode); |
424 inputs[input_count++] = val; | 229 inputs[input_count++] = val; |
425 Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs); | 230 Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs); |
426 } | 231 } |
427 | 232 |
428 | 233 |
429 void InstructionSelector::VisitCheckedLoad(Node* node) { | 234 void InstructionSelector::VisitCheckedLoad(Node* node) { |
430 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 235 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
431 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 236 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
432 IA32OperandGenerator g(this); | 237 IA32OperandGenerator g(this); |
433 Node* const buffer = node->InputAt(0); | 238 Node* const buffer = node->InputAt(0); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 if (g.CanBeImmediate(right)) { | 464 if (g.CanBeImmediate(right)) { |
660 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 465 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
661 g.UseImmediate(right)); | 466 g.UseImmediate(right)); |
662 } else { | 467 } else { |
663 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 468 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
664 g.UseFixed(right, ecx)); | 469 g.UseFixed(right, ecx)); |
665 } | 470 } |
666 } | 471 } |
667 | 472 |
668 | 473 |
| 474 namespace { |
| 475 |
| 476 void VisitMulHigh(InstructionSelector* selector, Node* node, |
| 477 ArchOpcode opcode) { |
| 478 IA32OperandGenerator g(selector); |
| 479 selector->Emit(opcode, g.DefineAsFixed(node, edx), |
| 480 g.UseFixed(node->InputAt(0), eax), |
| 481 g.UseUniqueRegister(node->InputAt(1))); |
| 482 } |
| 483 |
| 484 |
| 485 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| 486 IA32OperandGenerator g(selector); |
| 487 InstructionOperand* temps[] = {g.TempRegister(edx)}; |
| 488 selector->Emit(opcode, g.DefineAsFixed(node, eax), |
| 489 g.UseFixed(node->InputAt(0), eax), |
| 490 g.UseUnique(node->InputAt(1)), arraysize(temps), temps); |
| 491 } |
| 492 |
| 493 |
| 494 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| 495 IA32OperandGenerator g(selector); |
| 496 selector->Emit(opcode, g.DefineAsFixed(node, edx), |
| 497 g.UseFixed(node->InputAt(0), eax), |
| 498 g.UseUnique(node->InputAt(1))); |
| 499 } |
| 500 |
| 501 void EmitLea(InstructionSelector* selector, Node* result, Node* index, |
| 502 int scale, Node* base, Node* displacement) { |
| 503 IA32OperandGenerator g(selector); |
| 504 InstructionOperand* inputs[4]; |
| 505 size_t input_count = 0; |
| 506 AddressingMode mode = g.GenerateMemoryOperandInputs( |
| 507 index, scale, base, displacement, inputs, &input_count); |
| 508 |
| 509 DCHECK_NE(0, static_cast<int>(input_count)); |
| 510 DCHECK_GE(arraysize(inputs), input_count); |
| 511 |
| 512 InstructionOperand* outputs[1]; |
| 513 outputs[0] = g.DefineAsRegister(result); |
| 514 |
| 515 InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea; |
| 516 |
| 517 selector->Emit(opcode, 1, outputs, input_count, inputs); |
| 518 } |
| 519 |
| 520 } // namespace |
| 521 |
| 522 |
669 void InstructionSelector::VisitWord32Shl(Node* node) { | 523 void InstructionSelector::VisitWord32Shl(Node* node) { |
| 524 Int32ScaleMatcher m(node, true); |
| 525 if (m.matches()) { |
| 526 Node* index = node->InputAt(0); |
| 527 Node* base = m.power_of_two_plus_one() ? index : NULL; |
| 528 EmitLea(this, node, index, m.scale(), base, NULL); |
| 529 return; |
| 530 } |
670 VisitShift(this, node, kIA32Shl); | 531 VisitShift(this, node, kIA32Shl); |
671 } | 532 } |
672 | 533 |
673 | 534 |
674 void InstructionSelector::VisitWord32Shr(Node* node) { | 535 void InstructionSelector::VisitWord32Shr(Node* node) { |
675 VisitShift(this, node, kIA32Shr); | 536 VisitShift(this, node, kIA32Shr); |
676 } | 537 } |
677 | 538 |
678 | 539 |
679 void InstructionSelector::VisitWord32Sar(Node* node) { | 540 void InstructionSelector::VisitWord32Sar(Node* node) { |
680 VisitShift(this, node, kIA32Sar); | 541 VisitShift(this, node, kIA32Sar); |
681 } | 542 } |
682 | 543 |
683 | 544 |
684 void InstructionSelector::VisitWord32Ror(Node* node) { | 545 void InstructionSelector::VisitWord32Ror(Node* node) { |
685 VisitShift(this, node, kIA32Ror); | 546 VisitShift(this, node, kIA32Ror); |
686 } | 547 } |
687 | 548 |
688 | 549 |
689 static bool TryEmitLeaMultAdd(InstructionSelector* selector, Node* node) { | |
690 Int32BinopMatcher m(node); | |
691 if (!m.right().HasValue()) return false; | |
692 int32_t displacement_value = m.right().Value(); | |
693 Node* left = m.left().node(); | |
694 LeaMultiplyMatcher lmm(left); | |
695 if (!lmm.Matches()) return false; | |
696 AddressingMode mode; | |
697 size_t input_count; | |
698 IA32OperandGenerator g(selector); | |
699 InstructionOperand* index = g.UseRegister(lmm.Left()); | |
700 InstructionOperand* displacement = g.TempImmediate(displacement_value); | |
701 InstructionOperand* inputs[] = {index, displacement, displacement}; | |
702 if (lmm.Displacement() != 0) { | |
703 input_count = 3; | |
704 inputs[1] = index; | |
705 mode = kMode_MR1I; | |
706 } else { | |
707 input_count = 2; | |
708 mode = kMode_M1I; | |
709 } | |
710 mode = AdjustAddressingMode(mode, lmm.Power()); | |
711 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; | |
712 selector->Emit(kIA32Lea | AddressingModeField::encode(mode), 1, outputs, | |
713 input_count, inputs); | |
714 return true; | |
715 } | |
716 | |
717 | |
718 void InstructionSelector::VisitInt32Add(Node* node) { | 550 void InstructionSelector::VisitInt32Add(Node* node) { |
719 if (TryEmitLeaMultAdd(this, node)) return; | 551 IA32OperandGenerator g(this); |
| 552 |
| 553 // Try to match the Add to a lea pattern |
| 554 BaseWithIndexAndDisplacement32Matcher m(node); |
| 555 if (m.matches() && |
| 556 (m.displacement() == NULL || g.CanBeImmediate(m.displacement()))) { |
| 557 InstructionOperand* inputs[4]; |
| 558 size_t input_count = 0; |
| 559 AddressingMode mode = g.GenerateMemoryOperandInputs( |
| 560 m.index(), m.scale(), m.base(), m.displacement(), inputs, &input_count); |
| 561 |
| 562 DCHECK_NE(0, static_cast<int>(input_count)); |
| 563 DCHECK_GE(arraysize(inputs), input_count); |
| 564 |
| 565 InstructionOperand* outputs[1]; |
| 566 outputs[0] = g.DefineAsRegister(node); |
| 567 |
| 568 InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea; |
| 569 Emit(opcode, 1, outputs, input_count, inputs); |
| 570 return; |
| 571 } |
| 572 |
| 573 // No lea pattern match, use add |
720 VisitBinop(this, node, kIA32Add); | 574 VisitBinop(this, node, kIA32Add); |
721 } | 575 } |
722 | 576 |
723 | 577 |
724 void InstructionSelector::VisitInt32Sub(Node* node) { | 578 void InstructionSelector::VisitInt32Sub(Node* node) { |
725 IA32OperandGenerator g(this); | 579 IA32OperandGenerator g(this); |
726 Int32BinopMatcher m(node); | 580 Int32BinopMatcher m(node); |
727 if (m.left().Is(0)) { | 581 if (m.left().Is(0)) { |
728 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); | 582 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); |
729 } else { | 583 } else { |
730 VisitBinop(this, node, kIA32Sub); | 584 VisitBinop(this, node, kIA32Sub); |
731 } | 585 } |
732 } | 586 } |
733 | 587 |
734 | 588 |
735 static bool TryEmitLeaMult(InstructionSelector* selector, Node* node) { | |
736 LeaMultiplyMatcher lea(node); | |
737 // Try to match lea. | |
738 if (!lea.Matches()) return false; | |
739 AddressingMode mode; | |
740 size_t input_count; | |
741 IA32OperandGenerator g(selector); | |
742 InstructionOperand* left = g.UseRegister(lea.Left()); | |
743 InstructionOperand* inputs[] = {left, left}; | |
744 if (lea.Displacement() != 0) { | |
745 input_count = 2; | |
746 mode = kMode_MR1; | |
747 } else { | |
748 input_count = 1; | |
749 mode = kMode_M1; | |
750 } | |
751 mode = AdjustAddressingMode(mode, lea.Power()); | |
752 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; | |
753 selector->Emit(kIA32Lea | AddressingModeField::encode(mode), 1, outputs, | |
754 input_count, inputs); | |
755 return true; | |
756 } | |
757 | |
758 | |
759 void InstructionSelector::VisitInt32Mul(Node* node) { | 589 void InstructionSelector::VisitInt32Mul(Node* node) { |
760 if (TryEmitLeaMult(this, node)) return; | 590 Int32ScaleMatcher m(node, true); |
| 591 if (m.matches()) { |
| 592 Node* index = node->InputAt(0); |
| 593 Node* base = m.power_of_two_plus_one() ? index : NULL; |
| 594 EmitLea(this, node, index, m.scale(), base, NULL); |
| 595 return; |
| 596 } |
761 IA32OperandGenerator g(this); | 597 IA32OperandGenerator g(this); |
762 Int32BinopMatcher m(node); | 598 Node* left = node->InputAt(0); |
763 Node* left = m.left().node(); | 599 Node* right = node->InputAt(1); |
764 Node* right = m.right().node(); | |
765 if (g.CanBeImmediate(right)) { | 600 if (g.CanBeImmediate(right)) { |
766 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), | 601 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), |
767 g.UseImmediate(right)); | 602 g.UseImmediate(right)); |
768 } else { | 603 } else { |
769 if (g.CanBeBetterLeftOperand(right)) { | 604 if (g.CanBeBetterLeftOperand(right)) { |
770 std::swap(left, right); | 605 std::swap(left, right); |
771 } | 606 } |
772 Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), | 607 Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), |
773 g.Use(right)); | 608 g.Use(right)); |
774 } | 609 } |
775 } | 610 } |
776 | 611 |
777 | 612 |
778 namespace { | |
779 | |
780 void VisitMulHigh(InstructionSelector* selector, Node* node, | |
781 ArchOpcode opcode) { | |
782 IA32OperandGenerator g(selector); | |
783 selector->Emit(opcode, g.DefineAsFixed(node, edx), | |
784 g.UseFixed(node->InputAt(0), eax), | |
785 g.UseUniqueRegister(node->InputAt(1))); | |
786 } | |
787 | |
788 | |
789 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | |
790 IA32OperandGenerator g(selector); | |
791 InstructionOperand* temps[] = {g.TempRegister(edx)}; | |
792 selector->Emit(opcode, g.DefineAsFixed(node, eax), | |
793 g.UseFixed(node->InputAt(0), eax), | |
794 g.UseUnique(node->InputAt(1)), arraysize(temps), temps); | |
795 } | |
796 | |
797 | |
798 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | |
799 IA32OperandGenerator g(selector); | |
800 selector->Emit(opcode, g.DefineAsFixed(node, edx), | |
801 g.UseFixed(node->InputAt(0), eax), | |
802 g.UseUnique(node->InputAt(1))); | |
803 } | |
804 | |
805 } // namespace | |
806 | |
807 | |
808 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 613 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
809 VisitMulHigh(this, node, kIA32ImulHigh); | 614 VisitMulHigh(this, node, kIA32ImulHigh); |
810 } | 615 } |
811 | 616 |
812 | 617 |
813 void InstructionSelector::VisitUint32MulHigh(Node* node) { | 618 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
814 VisitMulHigh(this, node, kIA32UmulHigh); | 619 VisitMulHigh(this, node, kIA32UmulHigh); |
815 } | 620 } |
816 | 621 |
817 | 622 |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1242 return MachineOperatorBuilder::kFloat64Floor | | 1047 return MachineOperatorBuilder::kFloat64Floor | |
1243 MachineOperatorBuilder::kFloat64Ceil | | 1048 MachineOperatorBuilder::kFloat64Ceil | |
1244 MachineOperatorBuilder::kFloat64RoundTruncate | | 1049 MachineOperatorBuilder::kFloat64RoundTruncate | |
1245 MachineOperatorBuilder::kWord32ShiftIsSafe; | 1050 MachineOperatorBuilder::kWord32ShiftIsSafe; |
1246 } | 1051 } |
1247 return MachineOperatorBuilder::Flag::kNoFlags; | 1052 return MachineOperatorBuilder::Flag::kNoFlags; |
1248 } | 1053 } |
1249 } // namespace compiler | 1054 } // namespace compiler |
1250 } // namespace internal | 1055 } // namespace internal |
1251 } // namespace v8 | 1056 } // namespace v8 |
OLD | NEW |