Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(315)

Side by Side Diff: src/compiler/ia32/instruction-selector-ia32.cc

Issue 747283005: [turbofan]: Port lea changes to ia32 (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: For Dan Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/ia32/code-generator-ia32.cc ('k') | src/compiler/node-matchers.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/ia32/code-generator-ia32.cc ('k') | src/compiler/node-matchers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698