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

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

Issue 2087233005: [arm64] Fix handling of CMN and ADD/SUB with overflow in VisitBinop. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 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
« no previous file with comments | « no previous file | test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc » ('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.h" 7 #include "src/compiler/node-properties.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 return false; 249 return false;
250 } 250 }
251 *index_op = g->UseRegister(left); 251 *index_op = g->UseRegister(left);
252 *shift_immediate_op = g->UseImmediate(right); 252 *shift_immediate_op = g->UseImmediate(right);
253 return true; 253 return true;
254 default: 254 default:
255 return false; 255 return false;
256 } 256 }
257 } 257 }
258 258
259 // Bitfields describing binary operator properties:
260 // CanCommuteField is true if we can switch the two operands, potentially
261 // requiring commuting the flags continuation condition.
262 typedef BitField8<bool, 1, 1> CanCommuteField;
263 // MustCommuteCondField is true when we need to commute the flags continuation
264 // condition in order to switch the operands.
265 typedef BitField8<bool, 2, 1> MustCommuteCondField;
266 // IsComparisonField is true when the operation is a comparison and has no other
267 // result other than the condition.
268 typedef BitField8<bool, 3, 1> IsComparisonField;
269 // IsAddSubField is true when an instruction is encoded as ADD or SUB.
270 typedef BitField8<bool, 4, 1> IsAddSubField;
271
272 // Get properties of a binary operator.
273 uint8_t GetBinopProperties(InstructionCode opcode) {
274 uint8_t result = 0;
275 switch (opcode) {
276 case kArm64Cmp32:
277 case kArm64Cmp:
278 // We can commute CMP by switching the inputs and commuting
279 // the flags continuation.
280 result = CanCommuteField::update(result, true);
281 result = MustCommuteCondField::update(result, true);
282 result = IsComparisonField::update(result, true);
283 // The CMP and CMN instructions are encoded as SUB or ADD
284 // with zero output register, and therefore support the same
285 // operand modes.
286 result = IsAddSubField::update(result, true);
287 break;
288 case kArm64Cmn32:
289 case kArm64Cmn:
290 result = CanCommuteField::update(result, true);
291 result = IsComparisonField::update(result, true);
292 result = IsAddSubField::update(result, true);
293 break;
294 case kArm64Add32:
295 case kArm64Add:
296 result = CanCommuteField::update(result, true);
297 result = IsAddSubField::update(result, true);
298 break;
299 case kArm64Sub32:
300 case kArm64Sub:
301 result = IsAddSubField::update(result, true);
302 break;
303 case kArm64Tst32:
304 case kArm64Tst:
305 result = CanCommuteField::update(result, true);
306 result = IsComparisonField::update(result, true);
307 break;
308 case kArm64And32:
309 case kArm64And:
310 case kArm64Or32:
311 case kArm64Or:
312 case kArm64Eor32:
313 case kArm64Eor:
314 result = CanCommuteField::update(result, true);
315 break;
316 default:
317 UNREACHABLE();
318 return 0;
319 }
320 DCHECK_IMPLIES(MustCommuteCondField::decode(result),
321 CanCommuteField::decode(result));
322 return result;
323 }
324
259 // Shared routine for multiple binary operations. 325 // Shared routine for multiple binary operations.
260 template <typename Matcher> 326 template <typename Matcher>
261 void VisitBinop(InstructionSelector* selector, Node* node, 327 void VisitBinop(InstructionSelector* selector, Node* node,
262 InstructionCode opcode, ImmediateMode operand_mode, 328 InstructionCode opcode, ImmediateMode operand_mode,
263 FlagsContinuation* cont) { 329 FlagsContinuation* cont) {
264 Arm64OperandGenerator g(selector); 330 Arm64OperandGenerator g(selector);
265 Matcher m(node);
266 InstructionOperand inputs[5]; 331 InstructionOperand inputs[5];
267 size_t input_count = 0; 332 size_t input_count = 0;
268 InstructionOperand outputs[2]; 333 InstructionOperand outputs[2];
269 size_t output_count = 0; 334 size_t output_count = 0;
270 bool is_cmp = (opcode == kArm64Cmp32) || (opcode == kArm64Cmn32);
271 335
272 // We can commute cmp by switching the inputs and commuting the flags 336 Node* left_node = node->InputAt(0);
273 // continuation. 337 Node* right_node = node->InputAt(1);
274 bool can_commute = m.HasProperty(Operator::kCommutative) || is_cmp;
275 338
276 // The cmp and cmn instructions are encoded as sub or add with zero output 339 uint8_t properties = GetBinopProperties(opcode);
277 // register, and therefore support the same operand modes. 340 bool can_commute = CanCommuteField::decode(properties);
278 bool is_add_sub = m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || 341 bool must_commute_cond = MustCommuteCondField::decode(properties);
279 m.IsInt64Sub() || is_cmp; 342 bool is_add_sub = IsAddSubField::decode(properties);
280
281 Node* left_node = m.left().node();
282 Node* right_node = m.right().node();
283 343
284 if (g.CanBeImmediate(right_node, operand_mode)) { 344 if (g.CanBeImmediate(right_node, operand_mode)) {
285 inputs[input_count++] = g.UseRegister(left_node); 345 inputs[input_count++] = g.UseRegister(left_node);
286 inputs[input_count++] = g.UseImmediate(right_node); 346 inputs[input_count++] = g.UseImmediate(right_node);
287 } else if (is_cmp && g.CanBeImmediate(left_node, operand_mode)) { 347 } else if (can_commute && g.CanBeImmediate(left_node, operand_mode)) {
288 cont->Commute(); 348 if (must_commute_cond) cont->Commute();
289 inputs[input_count++] = g.UseRegister(right_node); 349 inputs[input_count++] = g.UseRegister(right_node);
290 inputs[input_count++] = g.UseImmediate(left_node); 350 inputs[input_count++] = g.UseImmediate(left_node);
291 } else if (is_add_sub && 351 } else if (is_add_sub &&
292 TryMatchAnyExtend(&g, selector, node, left_node, right_node, 352 TryMatchAnyExtend(&g, selector, node, left_node, right_node,
293 &inputs[0], &inputs[1], &opcode)) { 353 &inputs[0], &inputs[1], &opcode)) {
294 input_count += 2; 354 input_count += 2;
295 } else if (is_add_sub && can_commute && 355 } else if (is_add_sub && can_commute &&
296 TryMatchAnyExtend(&g, selector, node, right_node, left_node, 356 TryMatchAnyExtend(&g, selector, node, right_node, left_node,
297 &inputs[0], &inputs[1], &opcode)) { 357 &inputs[0], &inputs[1], &opcode)) {
298 if (is_cmp) cont->Commute(); 358 if (must_commute_cond) cont->Commute();
299 input_count += 2; 359 input_count += 2;
300 } else if (TryMatchAnyShift(selector, node, right_node, &opcode, 360 } else if (TryMatchAnyShift(selector, node, right_node, &opcode,
301 !is_add_sub)) { 361 !is_add_sub)) {
302 Matcher m_shift(right_node); 362 Matcher m_shift(right_node);
303 inputs[input_count++] = g.UseRegisterOrImmediateZero(left_node); 363 inputs[input_count++] = g.UseRegisterOrImmediateZero(left_node);
304 inputs[input_count++] = g.UseRegister(m_shift.left().node()); 364 inputs[input_count++] = g.UseRegister(m_shift.left().node());
305 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); 365 inputs[input_count++] = g.UseImmediate(m_shift.right().node());
306 } else if (can_commute && TryMatchAnyShift(selector, node, left_node, &opcode, 366 } else if (can_commute && TryMatchAnyShift(selector, node, left_node, &opcode,
307 !is_add_sub)) { 367 !is_add_sub)) {
308 if (is_cmp) cont->Commute(); 368 if (must_commute_cond) cont->Commute();
309 Matcher m_shift(left_node); 369 Matcher m_shift(left_node);
310 inputs[input_count++] = g.UseRegisterOrImmediateZero(right_node); 370 inputs[input_count++] = g.UseRegisterOrImmediateZero(right_node);
311 inputs[input_count++] = g.UseRegister(m_shift.left().node()); 371 inputs[input_count++] = g.UseRegister(m_shift.left().node());
312 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); 372 inputs[input_count++] = g.UseImmediate(m_shift.right().node());
313 } else { 373 } else {
314 inputs[input_count++] = g.UseRegisterOrImmediateZero(left_node); 374 inputs[input_count++] = g.UseRegisterOrImmediateZero(left_node);
315 inputs[input_count++] = g.UseRegister(right_node); 375 inputs[input_count++] = g.UseRegister(right_node);
316 } 376 }
317 377
318 if (cont->IsBranch()) { 378 if (cont->IsBranch()) {
319 inputs[input_count++] = g.Label(cont->true_block()); 379 inputs[input_count++] = g.Label(cont->true_block());
320 inputs[input_count++] = g.Label(cont->false_block()); 380 inputs[input_count++] = g.Label(cont->false_block());
321 } 381 }
322 382
323 if (!is_cmp) { 383 if (!IsComparisonField::decode(properties)) {
324 outputs[output_count++] = g.DefineAsRegister(node); 384 outputs[output_count++] = g.DefineAsRegister(node);
325 } 385 }
326 386
327 if (cont->IsSet()) { 387 if (cont->IsSet()) {
328 outputs[output_count++] = g.DefineAsRegister(cont->result()); 388 outputs[output_count++] = g.DefineAsRegister(cont->result());
329 } 389 }
330 390
331 DCHECK_NE(0u, input_count); 391 DCHECK_NE(0u, input_count);
332 DCHECK((output_count != 0) || is_cmp); 392 DCHECK((output_count != 0) || IsComparisonField::decode(properties));
333 DCHECK_GE(arraysize(inputs), input_count); 393 DCHECK_GE(arraysize(inputs), input_count);
334 DCHECK_GE(arraysize(outputs), output_count); 394 DCHECK_GE(arraysize(outputs), output_count);
335 395
336 opcode = cont->Encode(opcode); 396 opcode = cont->Encode(opcode);
337 if (cont->IsDeoptimize()) { 397 if (cont->IsDeoptimize()) {
338 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, 398 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
339 cont->frame_state()); 399 cont->frame_state());
340 } else { 400 } else {
341 selector->Emit(opcode, output_count, outputs, input_count, inputs); 401 selector->Emit(opcode, output_count, outputs, input_count, inputs);
342 } 402 }
(...skipping 2146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2489 // static 2549 // static
2490 MachineOperatorBuilder::AlignmentRequirements 2550 MachineOperatorBuilder::AlignmentRequirements
2491 InstructionSelector::AlignmentRequirements() { 2551 InstructionSelector::AlignmentRequirements() {
2492 return MachineOperatorBuilder::AlignmentRequirements:: 2552 return MachineOperatorBuilder::AlignmentRequirements::
2493 FullUnalignedAccessSupport(); 2553 FullUnalignedAccessSupport();
2494 } 2554 }
2495 2555
2496 } // namespace compiler 2556 } // namespace compiler
2497 } // namespace internal 2557 } // namespace internal
2498 } // namespace v8 2558 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698