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

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

Issue 434553002: [arm] Add support for ROR. Refactor operand2 handling. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 months 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 | Annotate | Revision Log
« no previous file with comments | « src/compiler/arm/instruction-codes-arm.h ('k') | test/cctest/compiler/codegen-tester.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-intrinsics.h" 7 #include "src/compiler-intrinsics.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 114
115 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, 115 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode,
116 Node* node) { 116 Node* node) {
117 ArmOperandGenerator g(selector); 117 ArmOperandGenerator g(selector);
118 selector->Emit(opcode, g.DefineAsDoubleRegister(node), 118 selector->Emit(opcode, g.DefineAsDoubleRegister(node),
119 g.UseDoubleRegister(node->InputAt(0)), 119 g.UseDoubleRegister(node->InputAt(0)),
120 g.UseDoubleRegister(node->InputAt(1))); 120 g.UseDoubleRegister(node->InputAt(1)));
121 } 121 }
122 122
123 123
124 static Instruction* EmitBinop(InstructionSelector* selector, 124 static bool TryMatchROR(InstructionSelector* selector,
125 InstructionCode opcode, size_t output_count, 125 InstructionCode* opcode_return, Node* node,
126 InstructionOperand** outputs, Node* left, 126 InstructionOperand** value_return,
127 Node* right, size_t label_count, 127 InstructionOperand** shift_return) {
128 InstructionOperand** labels) {
129 ArmOperandGenerator g(selector); 128 ArmOperandGenerator g(selector);
130 InstructionOperand* inputs[5]; 129 if (node->opcode() != IrOpcode::kWord32Or) return false;
131 size_t input_count = 0; 130 Int32BinopMatcher m(node);
132 131 Node* shl = m.left().node();
133 inputs[input_count++] = g.UseRegister(left); 132 Node* shr = m.right().node();
134 if (g.CanBeImmediate(right, opcode)) { 133 if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
135 opcode |= AddressingModeField::encode(kMode_Operand2_I); 134 std::swap(shl, shr);
136 inputs[input_count++] = g.UseImmediate(right); 135 } else if (!m.left().IsWord32Shl() || !m.right().IsWord32Shr()) {
137 } else if (right->opcode() == IrOpcode::kWord32Sar) { 136 return false;
138 Int32BinopMatcher mright(right);
139 inputs[input_count++] = g.UseRegister(mright.left().node());
140 if (mright.right().IsInRange(1, 32)) {
141 opcode |= AddressingModeField::encode(kMode_Operand2_R_ASR_I);
142 inputs[input_count++] = g.UseImmediate(mright.right().node());
143 } else {
144 opcode |= AddressingModeField::encode(kMode_Operand2_R_ASR_R);
145 inputs[input_count++] = g.UseRegister(mright.right().node());
146 }
147 } else if (right->opcode() == IrOpcode::kWord32Shl) {
148 Int32BinopMatcher mright(right);
149 inputs[input_count++] = g.UseRegister(mright.left().node());
150 if (mright.right().IsInRange(0, 31)) {
151 opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
152 inputs[input_count++] = g.UseImmediate(mright.right().node());
153 } else {
154 opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_R);
155 inputs[input_count++] = g.UseRegister(mright.right().node());
156 }
157 } else if (right->opcode() == IrOpcode::kWord32Shr) {
158 Int32BinopMatcher mright(right);
159 inputs[input_count++] = g.UseRegister(mright.left().node());
160 if (mright.right().IsInRange(1, 32)) {
161 opcode |= AddressingModeField::encode(kMode_Operand2_R_LSR_I);
162 inputs[input_count++] = g.UseImmediate(mright.right().node());
163 } else {
164 opcode |= AddressingModeField::encode(kMode_Operand2_R_LSR_R);
165 inputs[input_count++] = g.UseRegister(mright.right().node());
166 }
167 } else {
168 opcode |= AddressingModeField::encode(kMode_Operand2_R);
169 inputs[input_count++] = g.UseRegister(right);
170 } 137 }
171 138 Int32BinopMatcher mshr(shr);
172 // Append the optional labels. 139 Int32BinopMatcher mshl(shl);
173 while (label_count-- != 0) { 140 Node* value = mshr.left().node();
174 inputs[input_count++] = *labels++; 141 if (value != mshl.left().node()) return false;
142 Node* shift = mshr.right().node();
143 Int32Matcher mshift(shift);
144 if (mshift.IsInRange(1, 31) && mshl.right().Is(32 - mshift.Value())) {
145 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_I);
146 *value_return = g.UseRegister(value);
147 *shift_return = g.UseImmediate(shift);
148 return true;
175 } 149 }
176 150 if (mshl.right().IsInt32Sub()) {
177 ASSERT_NE(0, input_count); 151 Int32BinopMatcher mshlright(mshl.right().node());
178 ASSERT_GE(ARRAY_SIZE(inputs), input_count); 152 if (!mshlright.left().Is(32)) return false;
179 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); 153 if (mshlright.right().node() != shift) return false;
180 154 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_R);
181 return selector->Emit(opcode, output_count, outputs, input_count, inputs); 155 *value_return = g.UseRegister(value);
156 *shift_return = g.UseRegister(shift);
157 return true;
158 }
159 return false;
182 } 160 }
183 161
184 162
185 static Instruction* EmitBinop(InstructionSelector* selector, 163 static inline bool TryMatchASR(InstructionSelector* selector,
186 InstructionCode opcode, Node* node, Node* left, 164 InstructionCode* opcode_return, Node* node,
187 Node* right) { 165 InstructionOperand** value_return,
166 InstructionOperand** shift_return) {
188 ArmOperandGenerator g(selector); 167 ArmOperandGenerator g(selector);
189 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; 168 if (node->opcode() != IrOpcode::kWord32Sar) return false;
190 const size_t output_count = ARRAY_SIZE(outputs); 169 Int32BinopMatcher m(node);
191 return EmitBinop(selector, opcode, output_count, outputs, left, right, 0, 170 *value_return = g.UseRegister(m.left().node());
192 NULL); 171 if (m.right().IsInRange(1, 32)) {
172 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_I);
173 *shift_return = g.UseImmediate(m.right().node());
174 } else {
175 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_R);
176 *shift_return = g.UseRegister(m.right().node());
177 }
178 return true;
193 } 179 }
194 180
195 181
182 static inline bool TryMatchLSL(InstructionSelector* selector,
183 InstructionCode* opcode_return, Node* node,
184 InstructionOperand** value_return,
185 InstructionOperand** shift_return) {
186 ArmOperandGenerator g(selector);
187 if (node->opcode() != IrOpcode::kWord32Shl) return false;
188 Int32BinopMatcher m(node);
189 *value_return = g.UseRegister(m.left().node());
190 if (m.right().IsInRange(0, 31)) {
191 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
192 *shift_return = g.UseImmediate(m.right().node());
193 } else {
194 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_R);
195 *shift_return = g.UseRegister(m.right().node());
196 }
197 return true;
198 }
199
200
201 static inline bool TryMatchLSR(InstructionSelector* selector,
202 InstructionCode* opcode_return, Node* node,
203 InstructionOperand** value_return,
204 InstructionOperand** shift_return) {
205 ArmOperandGenerator g(selector);
206 if (node->opcode() != IrOpcode::kWord32Shr) return false;
207 Int32BinopMatcher m(node);
208 *value_return = g.UseRegister(m.left().node());
209 if (m.right().IsInRange(1, 32)) {
210 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_I);
211 *shift_return = g.UseImmediate(m.right().node());
212 } else {
213 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_R);
214 *shift_return = g.UseRegister(m.right().node());
215 }
216 return true;
217 }
218
219
220 static inline bool TryMatchImmediateOrShift(InstructionSelector* selector,
221 InstructionCode* opcode_return,
222 Node* node,
223 size_t* input_count_return,
224 InstructionOperand** inputs) {
225 ArmOperandGenerator g(selector);
226 if (g.CanBeImmediate(node, *opcode_return)) {
227 *opcode_return |= AddressingModeField::encode(kMode_Operand2_I);
228 inputs[0] = g.UseImmediate(node);
229 *input_count_return = 1;
230 return true;
231 }
232 if (TryMatchASR(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
233 TryMatchLSL(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
234 TryMatchLSR(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
235 TryMatchROR(selector, opcode_return, node, &inputs[0], &inputs[1])) {
236 *input_count_return = 2;
237 return true;
238 }
239 return false;
240 }
241
242
196 // Shared routine for multiple binary operations. 243 // Shared routine for multiple binary operations.
197 static void VisitBinop(InstructionSelector* selector, Node* node, 244 static void VisitBinop(InstructionSelector* selector, Node* node,
198 InstructionCode opcode, InstructionCode reverse_opcode) { 245 InstructionCode opcode, InstructionCode reverse_opcode) {
199 ArmOperandGenerator g(selector); 246 ArmOperandGenerator g(selector);
200 Int32BinopMatcher m(node); 247 Int32BinopMatcher m(node);
248 InstructionOperand* inputs[3];
249 size_t input_count = 0;
201 250
202 Node* left = m.left().node(); 251 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
203 Node* right = m.right().node(); 252 &input_count, &inputs[1])) {
204 if (g.CanBeImmediate(m.left().node(), reverse_opcode) || 253 inputs[0] = g.UseRegister(m.left().node());
205 m.left().IsWord32Sar() || m.left().IsWord32Shl() || 254 input_count++;
206 m.left().IsWord32Shr()) { 255 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode,
256 m.left().node(), &input_count,
257 &inputs[1])) {
258 inputs[0] = g.UseRegister(m.right().node());
207 opcode = reverse_opcode; 259 opcode = reverse_opcode;
208 std::swap(left, right); 260 input_count++;
261 } else {
262 opcode |= AddressingModeField::encode(kMode_Operand2_R);
263 inputs[input_count++] = g.UseRegister(m.left().node());
264 inputs[input_count++] = g.UseRegister(m.right().node());
209 } 265 }
210 266
211 EmitBinop(selector, opcode, node, left, right); 267 ASSERT_NE(0, input_count);
268 ASSERT_GE(ARRAY_SIZE(inputs), input_count);
269 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode));
270
271 InstructionOperand* outputs[1] = {g.DefineAsRegister(node)};
272 const size_t output_count = ARRAY_SIZE(outputs);
273 selector->Emit(opcode, output_count, outputs, input_count, inputs);
212 } 274 }
213 275
214 276
215 void InstructionSelector::VisitLoad(Node* node) { 277 void InstructionSelector::VisitLoad(Node* node) {
216 MachineRepresentation rep = OpParameter<MachineRepresentation>(node); 278 MachineRepresentation rep = OpParameter<MachineRepresentation>(node);
217 ArmOperandGenerator g(this); 279 ArmOperandGenerator g(this);
218 Node* base = node->InputAt(0); 280 Node* base = node->InputAt(0);
219 Node* index = node->InputAt(1); 281 Node* index = node->InputAt(1);
220 282
221 InstructionOperand* result = rep == kMachineFloat64 283 InstructionOperand* result = rep == kMachineFloat64
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 } else if (g.CanBeImmediate(base, opcode)) { 366 } else if (g.CanBeImmediate(base, opcode)) {
305 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL, 367 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL,
306 g.UseRegister(index), g.UseImmediate(base), val); 368 g.UseRegister(index), g.UseImmediate(base), val);
307 } else { 369 } else {
308 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL, 370 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL,
309 g.UseRegister(base), g.UseRegister(index), val); 371 g.UseRegister(base), g.UseRegister(index), val);
310 } 372 }
311 } 373 }
312 374
313 375
376 static inline void EmitBic(InstructionSelector* selector, Node* node,
377 Node* left, Node* right) {
378 ArmOperandGenerator g(selector);
379 InstructionCode opcode = kArmBic;
380 InstructionOperand* inputs[3];
381 size_t input_count = 0;
382 InstructionOperand* outputs[1] = {g.DefineAsRegister(node)};
383 const size_t output_count = ARRAY_SIZE(outputs);
384
385 inputs[input_count++] = g.UseRegister(left);
386 if (!TryMatchImmediateOrShift(selector, &opcode, right, &input_count,
387 &inputs[input_count])) {
388 opcode |= AddressingModeField::encode(kMode_Operand2_R);
389 inputs[input_count++] = g.UseRegister(right);
390 }
391
392 ASSERT_NE(0, input_count);
393 ASSERT_GE(ARRAY_SIZE(inputs), input_count);
394 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode));
395
396 selector->Emit(opcode, output_count, outputs, input_count, inputs);
397 }
398
399
314 void InstructionSelector::VisitWord32And(Node* node) { 400 void InstructionSelector::VisitWord32And(Node* node) {
315 ArmOperandGenerator g(this); 401 ArmOperandGenerator g(this);
316 Int32BinopMatcher m(node); 402 Int32BinopMatcher m(node);
317 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) { 403 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) {
318 Int32BinopMatcher mleft(m.left().node()); 404 Int32BinopMatcher mleft(m.left().node());
319 if (mleft.right().Is(-1)) { 405 if (mleft.right().Is(-1)) {
320 EmitBinop(this, kArmBic, node, m.right().node(), mleft.left().node()); 406 EmitBic(this, node, m.right().node(), mleft.left().node());
321 return; 407 return;
322 } 408 }
323 } 409 }
324 if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) { 410 if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) {
325 Int32BinopMatcher mright(m.right().node()); 411 Int32BinopMatcher mright(m.right().node());
326 if (mright.right().Is(-1)) { 412 if (mright.right().Is(-1)) {
327 EmitBinop(this, kArmBic, node, m.left().node(), mright.left().node()); 413 EmitBic(this, node, m.left().node(), mright.left().node());
328 return; 414 return;
329 } 415 }
330 } 416 }
331 if (CpuFeatures::IsSupported(ARMv7) && m.right().HasValue()) { 417 if (CpuFeatures::IsSupported(ARMv7) && m.right().HasValue()) {
332 uint32_t value = m.right().Value(); 418 uint32_t value = m.right().Value();
333 uint32_t width = CompilerIntrinsics::CountSetBits(value); 419 uint32_t width = CompilerIntrinsics::CountSetBits(value);
334 uint32_t msb = CompilerIntrinsics::CountLeadingZeros(value); 420 uint32_t msb = CompilerIntrinsics::CountLeadingZeros(value);
335 if (msb + width == 32) { 421 if (msb + width == 32) {
336 ASSERT_EQ(0, CompilerIntrinsics::CountTrailingZeros(value)); 422 ASSERT_EQ(0, CompilerIntrinsics::CountTrailingZeros(value));
337 if (m.left().IsWord32Shr()) { 423 if (m.left().IsWord32Shr()) {
(...skipping 17 matching lines...) Expand all
355 Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), 441 Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
356 g.TempImmediate(lsb), g.TempImmediate(width)); 442 g.TempImmediate(lsb), g.TempImmediate(width));
357 return; 443 return;
358 } 444 }
359 } 445 }
360 VisitBinop(this, node, kArmAnd, kArmAnd); 446 VisitBinop(this, node, kArmAnd, kArmAnd);
361 } 447 }
362 448
363 449
364 void InstructionSelector::VisitWord32Or(Node* node) { 450 void InstructionSelector::VisitWord32Or(Node* node) {
451 ArmOperandGenerator g(this);
452 InstructionCode opcode = kArmMov;
453 InstructionOperand* value_operand;
454 InstructionOperand* shift_operand;
455 if (TryMatchROR(this, &opcode, node, &value_operand, &shift_operand)) {
456 Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand);
457 return;
458 }
365 VisitBinop(this, node, kArmOrr, kArmOrr); 459 VisitBinop(this, node, kArmOrr, kArmOrr);
366 } 460 }
367 461
368 462
369 void InstructionSelector::VisitWord32Xor(Node* node) { 463 void InstructionSelector::VisitWord32Xor(Node* node) {
370 ArmOperandGenerator g(this); 464 ArmOperandGenerator g(this);
371 Int32BinopMatcher m(node); 465 Int32BinopMatcher m(node);
372 if (m.right().Is(-1)) { 466 if (m.right().Is(-1)) {
373 Emit(kArmMvn | AddressingModeField::encode(kMode_Operand2_R), 467 Emit(kArmMvn | AddressingModeField::encode(kMode_Operand2_R),
374 g.DefineSameAsFirst(node), g.UseRegister(m.left().node())); 468 g.DefineSameAsFirst(node), g.UseRegister(m.left().node()));
375 } else { 469 } else {
376 VisitBinop(this, node, kArmEor, kArmEor); 470 VisitBinop(this, node, kArmEor, kArmEor);
377 } 471 }
378 } 472 }
379 473
380 474
475 template <typename TryMatchShift>
476 static inline void VisitShift(InstructionSelector* selector, Node* node,
477 TryMatchShift try_match_shift) {
478 ArmOperandGenerator g(selector);
479 InstructionCode opcode = kArmMov;
480 InstructionOperand* value_operand = NULL;
481 InstructionOperand* shift_operand = NULL;
482 CHECK(
483 try_match_shift(selector, &opcode, node, &value_operand, &shift_operand));
484 selector->Emit(opcode, g.DefineAsRegister(node), value_operand,
485 shift_operand);
486 }
487
488
381 void InstructionSelector::VisitWord32Shl(Node* node) { 489 void InstructionSelector::VisitWord32Shl(Node* node) {
382 ArmOperandGenerator g(this); 490 VisitShift(this, node, TryMatchLSL);
383 Int32BinopMatcher m(node);
384 if (m.right().IsInRange(0, 31)) {
385 Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
386 g.DefineAsRegister(node), g.UseRegister(m.left().node()),
387 g.UseImmediate(m.right().node()));
388 } else {
389 Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_LSL_R),
390 g.DefineAsRegister(node), g.UseRegister(m.left().node()),
391 g.UseRegister(m.right().node()));
392 }
393 } 491 }
394 492
395 493
396 void InstructionSelector::VisitWord32Shr(Node* node) { 494 void InstructionSelector::VisitWord32Shr(Node* node) {
397 ArmOperandGenerator g(this); 495 ArmOperandGenerator g(this);
398 Int32BinopMatcher m(node); 496 Int32BinopMatcher m(node);
399 if (CpuFeatures::IsSupported(ARMv7) && m.left().IsWord32And() && 497 if (CpuFeatures::IsSupported(ARMv7) && m.left().IsWord32And() &&
400 m.right().IsInRange(0, 31)) { 498 m.right().IsInRange(0, 31)) {
401 int32_t lsb = m.right().Value(); 499 int32_t lsb = m.right().Value();
402 Int32BinopMatcher mleft(m.left().node()); 500 Int32BinopMatcher mleft(m.left().node());
403 if (mleft.right().HasValue()) { 501 if (mleft.right().HasValue()) {
404 uint32_t value = (mleft.right().Value() >> lsb) << lsb; 502 uint32_t value = (mleft.right().Value() >> lsb) << lsb;
405 uint32_t width = CompilerIntrinsics::CountSetBits(value); 503 uint32_t width = CompilerIntrinsics::CountSetBits(value);
406 uint32_t msb = CompilerIntrinsics::CountLeadingZeros(value); 504 uint32_t msb = CompilerIntrinsics::CountLeadingZeros(value);
407 if (msb + width + lsb == 32) { 505 if (msb + width + lsb == 32) {
408 ASSERT_EQ(lsb, CompilerIntrinsics::CountTrailingZeros(value)); 506 ASSERT_EQ(lsb, CompilerIntrinsics::CountTrailingZeros(value));
409 Emit(kArmUbfx, g.DefineAsRegister(node), 507 Emit(kArmUbfx, g.DefineAsRegister(node),
410 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), 508 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb),
411 g.TempImmediate(width)); 509 g.TempImmediate(width));
412 return; 510 return;
413 } 511 }
414 } 512 }
415 } 513 }
416 if (m.right().IsInRange(1, 32)) { 514 VisitShift(this, node, TryMatchLSR);
417 Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_LSR_I),
418 g.DefineAsRegister(node), g.UseRegister(m.left().node()),
419 g.UseImmediate(m.right().node()));
420 return;
421 }
422 Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_LSR_R),
423 g.DefineAsRegister(node), g.UseRegister(m.left().node()),
424 g.UseRegister(m.right().node()));
425 } 515 }
426 516
427 517
428 void InstructionSelector::VisitWord32Sar(Node* node) { 518 void InstructionSelector::VisitWord32Sar(Node* node) {
429 ArmOperandGenerator g(this); 519 VisitShift(this, node, TryMatchASR);
430 Int32BinopMatcher m(node);
431 if (m.right().IsInRange(1, 32)) {
432 Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_ASR_I),
433 g.DefineAsRegister(node), g.UseRegister(m.left().node()),
434 g.UseImmediate(m.right().node()));
435 } else {
436 Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_ASR_R),
437 g.DefineAsRegister(node), g.UseRegister(m.left().node()),
438 g.UseRegister(m.right().node()));
439 }
440 } 520 }
441 521
442 522
443 void InstructionSelector::VisitInt32Add(Node* node) { 523 void InstructionSelector::VisitInt32Add(Node* node) {
444 ArmOperandGenerator g(this); 524 ArmOperandGenerator g(this);
445 Int32BinopMatcher m(node); 525 Int32BinopMatcher m(node);
446 if (m.left().IsInt32Mul() && CanCover(node, m.left().node())) { 526 if (m.left().IsInt32Mul() && CanCover(node, m.left().node())) {
447 Int32BinopMatcher mleft(m.left().node()); 527 Int32BinopMatcher mleft(m.left().node());
448 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mleft.left().node()), 528 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mleft.left().node()),
449 g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node())); 529 g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node()));
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 } 784 }
705 } 785 }
706 786
707 787
708 // Shared routine for multiple compare operations. 788 // Shared routine for multiple compare operations.
709 static void VisitWordCompare(InstructionSelector* selector, Node* node, 789 static void VisitWordCompare(InstructionSelector* selector, Node* node,
710 InstructionCode opcode, FlagsContinuation* cont, 790 InstructionCode opcode, FlagsContinuation* cont,
711 bool commutative, bool requires_output) { 791 bool commutative, bool requires_output) {
712 ArmOperandGenerator g(selector); 792 ArmOperandGenerator g(selector);
713 Int32BinopMatcher m(node); 793 Int32BinopMatcher m(node);
794 InstructionOperand* inputs[5];
795 size_t input_count = 0;
796 InstructionOperand* outputs[1];
797 size_t output_count = 0;
714 798
715 Node* left = m.left().node(); 799 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
716 Node* right = m.right().node(); 800 &input_count, &inputs[1])) {
717 if (g.CanBeImmediate(m.left().node(), opcode) || m.left().IsWord32Sar() || 801 inputs[0] = g.UseRegister(m.left().node());
718 m.left().IsWord32Shl() || m.left().IsWord32Shr()) { 802 input_count++;
803 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
804 &input_count, &inputs[1])) {
719 if (!commutative) cont->Commute(); 805 if (!commutative) cont->Commute();
720 std::swap(left, right); 806 inputs[0] = g.UseRegister(m.right().node());
807 input_count++;
808 } else {
809 opcode |= AddressingModeField::encode(kMode_Operand2_R);
810 inputs[input_count++] = g.UseRegister(m.left().node());
811 inputs[input_count++] = g.UseRegister(m.right().node());
721 } 812 }
722 813
723 opcode = cont->Encode(opcode);
724 if (cont->IsBranch()) { 814 if (cont->IsBranch()) {
725 InstructionOperand* outputs[1];
726 size_t output_count = 0;
727 if (requires_output) { 815 if (requires_output) {
728 outputs[output_count++] = g.DefineAsRegister(node); 816 outputs[output_count++] = g.DefineAsRegister(node);
729 } 817 }
730 InstructionOperand* labels[] = {g.Label(cont->true_block()), 818 inputs[input_count++] = g.Label(cont->true_block());
731 g.Label(cont->false_block())}; 819 inputs[input_count++] = g.Label(cont->false_block());
732 const size_t label_count = ARRAY_SIZE(labels);
733 EmitBinop(selector, opcode, output_count, outputs, left, right, label_count,
734 labels)->MarkAsControl();
735 } else { 820 } else {
736 ASSERT(cont->IsSet()); 821 ASSERT(cont->IsSet());
737 EmitBinop(selector, opcode, cont->result(), left, right); 822 outputs[output_count++] = g.DefineAsRegister(cont->result());
738 } 823 }
824
825 ASSERT_NE(0, input_count);
826 ASSERT_GE(ARRAY_SIZE(inputs), input_count);
827 ASSERT_GE(ARRAY_SIZE(outputs), output_count);
828
829 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
830 outputs, input_count, inputs);
831 if (cont->IsBranch()) instr->MarkAsControl();
739 } 832 }
740 833
741 834
742 void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) { 835 void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) {
743 switch (node->opcode()) { 836 switch (node->opcode()) {
744 case IrOpcode::kInt32Add: 837 case IrOpcode::kInt32Add:
745 return VisitWordCompare(this, node, kArmCmn, cont, true, false); 838 return VisitWordCompare(this, node, kArmCmn, cont, true, false);
746 case IrOpcode::kInt32Sub: 839 case IrOpcode::kInt32Sub:
747 return VisitWordCompare(this, node, kArmCmp, cont, false, false); 840 return VisitWordCompare(this, node, kArmCmp, cont, false, false);
748 case IrOpcode::kWord32And: 841 case IrOpcode::kWord32And:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 ASSERT(cont->IsSet()); 880 ASSERT(cont->IsSet());
788 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), 881 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()),
789 g.UseDoubleRegister(m.left().node()), 882 g.UseDoubleRegister(m.left().node()),
790 g.UseDoubleRegister(m.right().node())); 883 g.UseDoubleRegister(m.right().node()));
791 } 884 }
792 } 885 }
793 886
794 } // namespace compiler 887 } // namespace compiler
795 } // namespace internal 888 } // namespace internal
796 } // namespace v8 889 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/arm/instruction-codes-arm.h ('k') | test/cctest/compiler/codegen-tester.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698