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

Unified 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, 6 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/arm64/instruction-selector-arm64.cc
diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc
index f9ee78f0e554dfded32a84c6903114460f43a11a..637acac58bb43f45ee547d33870c9028980bcbcc 100644
--- a/src/compiler/arm64/instruction-selector-arm64.cc
+++ b/src/compiler/arm64/instruction-selector-arm64.cc
@@ -256,36 +256,96 @@ bool TryMatchLoadStoreShift(Arm64OperandGenerator* g,
}
}
+// Bitfields describing binary operator properties:
+// CanCommuteField is true if we can switch the two operands, potentially
+// requiring commuting the flags continuation condition.
+typedef BitField8<bool, 1, 1> CanCommuteField;
+// MustCommuteCondField is true when we need to commute the flags continuation
+// condition in order to switch the operands.
+typedef BitField8<bool, 2, 1> MustCommuteCondField;
+// IsComparisonField is true when the operation is a comparison and has no other
+// result other than the condition.
+typedef BitField8<bool, 3, 1> IsComparisonField;
+// IsAddSubField is true when an instruction is encoded as ADD or SUB.
+typedef BitField8<bool, 4, 1> IsAddSubField;
+
+// Get properties of a binary operator.
+uint8_t GetBinopProperties(InstructionCode opcode) {
+ uint8_t result = 0;
+ switch (opcode) {
+ case kArm64Cmp32:
+ case kArm64Cmp:
+ // We can commute CMP by switching the inputs and commuting
+ // the flags continuation.
+ result = CanCommuteField::update(result, true);
+ result = MustCommuteCondField::update(result, true);
+ result = IsComparisonField::update(result, true);
+ // The CMP and CMN instructions are encoded as SUB or ADD
+ // with zero output register, and therefore support the same
+ // operand modes.
+ result = IsAddSubField::update(result, true);
+ break;
+ case kArm64Cmn32:
+ case kArm64Cmn:
+ result = CanCommuteField::update(result, true);
+ result = IsComparisonField::update(result, true);
+ result = IsAddSubField::update(result, true);
+ break;
+ case kArm64Add32:
+ case kArm64Add:
+ result = CanCommuteField::update(result, true);
+ result = IsAddSubField::update(result, true);
+ break;
+ case kArm64Sub32:
+ case kArm64Sub:
+ result = IsAddSubField::update(result, true);
+ break;
+ case kArm64Tst32:
+ case kArm64Tst:
+ result = CanCommuteField::update(result, true);
+ result = IsComparisonField::update(result, true);
+ break;
+ case kArm64And32:
+ case kArm64And:
+ case kArm64Or32:
+ case kArm64Or:
+ case kArm64Eor32:
+ case kArm64Eor:
+ result = CanCommuteField::update(result, true);
+ break;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+ DCHECK_IMPLIES(MustCommuteCondField::decode(result),
+ CanCommuteField::decode(result));
+ return result;
+}
+
// Shared routine for multiple binary operations.
template <typename Matcher>
void VisitBinop(InstructionSelector* selector, Node* node,
InstructionCode opcode, ImmediateMode operand_mode,
FlagsContinuation* cont) {
Arm64OperandGenerator g(selector);
- Matcher m(node);
InstructionOperand inputs[5];
size_t input_count = 0;
InstructionOperand outputs[2];
size_t output_count = 0;
- bool is_cmp = (opcode == kArm64Cmp32) || (opcode == kArm64Cmn32);
- // We can commute cmp by switching the inputs and commuting the flags
- // continuation.
- bool can_commute = m.HasProperty(Operator::kCommutative) || is_cmp;
+ Node* left_node = node->InputAt(0);
+ Node* right_node = node->InputAt(1);
- // The cmp and cmn instructions are encoded as sub or add with zero output
- // register, and therefore support the same operand modes.
- bool is_add_sub = m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() ||
- m.IsInt64Sub() || is_cmp;
-
- Node* left_node = m.left().node();
- Node* right_node = m.right().node();
+ uint8_t properties = GetBinopProperties(opcode);
+ bool can_commute = CanCommuteField::decode(properties);
+ bool must_commute_cond = MustCommuteCondField::decode(properties);
+ bool is_add_sub = IsAddSubField::decode(properties);
if (g.CanBeImmediate(right_node, operand_mode)) {
inputs[input_count++] = g.UseRegister(left_node);
inputs[input_count++] = g.UseImmediate(right_node);
- } else if (is_cmp && g.CanBeImmediate(left_node, operand_mode)) {
- cont->Commute();
+ } else if (can_commute && g.CanBeImmediate(left_node, operand_mode)) {
+ if (must_commute_cond) cont->Commute();
inputs[input_count++] = g.UseRegister(right_node);
inputs[input_count++] = g.UseImmediate(left_node);
} else if (is_add_sub &&
@@ -295,7 +355,7 @@ void VisitBinop(InstructionSelector* selector, Node* node,
} else if (is_add_sub && can_commute &&
TryMatchAnyExtend(&g, selector, node, right_node, left_node,
&inputs[0], &inputs[1], &opcode)) {
- if (is_cmp) cont->Commute();
+ if (must_commute_cond) cont->Commute();
input_count += 2;
} else if (TryMatchAnyShift(selector, node, right_node, &opcode,
!is_add_sub)) {
@@ -305,7 +365,7 @@ void VisitBinop(InstructionSelector* selector, Node* node,
inputs[input_count++] = g.UseImmediate(m_shift.right().node());
} else if (can_commute && TryMatchAnyShift(selector, node, left_node, &opcode,
!is_add_sub)) {
- if (is_cmp) cont->Commute();
+ if (must_commute_cond) cont->Commute();
Matcher m_shift(left_node);
inputs[input_count++] = g.UseRegisterOrImmediateZero(right_node);
inputs[input_count++] = g.UseRegister(m_shift.left().node());
@@ -320,7 +380,7 @@ void VisitBinop(InstructionSelector* selector, Node* node,
inputs[input_count++] = g.Label(cont->false_block());
}
- if (!is_cmp) {
+ if (!IsComparisonField::decode(properties)) {
outputs[output_count++] = g.DefineAsRegister(node);
}
@@ -329,7 +389,7 @@ void VisitBinop(InstructionSelector* selector, Node* node,
}
DCHECK_NE(0u, input_count);
- DCHECK((output_count != 0) || is_cmp);
+ DCHECK((output_count != 0) || IsComparisonField::decode(properties));
DCHECK_GE(arraysize(inputs), input_count);
DCHECK_GE(arraysize(outputs), output_count);
« 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