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

Unified 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, 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/arm/instruction-selector-arm.cc
diff --git a/src/compiler/arm/instruction-selector-arm.cc b/src/compiler/arm/instruction-selector-arm.cc
index 95e3333669d8e8592dff60169af3f115b67958ec..03b0565487017a836ab5495016d06971ba1184f9 100644
--- a/src/compiler/arm/instruction-selector-arm.cc
+++ b/src/compiler/arm/instruction-selector-arm.cc
@@ -121,75 +121,122 @@ static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode,
}
-static Instruction* EmitBinop(InstructionSelector* selector,
- InstructionCode opcode, size_t output_count,
- InstructionOperand** outputs, Node* left,
- Node* right, size_t label_count,
- InstructionOperand** labels) {
+static bool TryMatchROR(InstructionSelector* selector,
+ InstructionCode* opcode_return, Node* node,
+ InstructionOperand** value_return,
+ InstructionOperand** shift_return) {
ArmOperandGenerator g(selector);
- InstructionOperand* inputs[5];
- size_t input_count = 0;
-
- inputs[input_count++] = g.UseRegister(left);
- if (g.CanBeImmediate(right, opcode)) {
- opcode |= AddressingModeField::encode(kMode_Operand2_I);
- inputs[input_count++] = g.UseImmediate(right);
- } else if (right->opcode() == IrOpcode::kWord32Sar) {
- Int32BinopMatcher mright(right);
- inputs[input_count++] = g.UseRegister(mright.left().node());
- if (mright.right().IsInRange(1, 32)) {
- opcode |= AddressingModeField::encode(kMode_Operand2_R_ASR_I);
- inputs[input_count++] = g.UseImmediate(mright.right().node());
- } else {
- opcode |= AddressingModeField::encode(kMode_Operand2_R_ASR_R);
- inputs[input_count++] = g.UseRegister(mright.right().node());
- }
- } else if (right->opcode() == IrOpcode::kWord32Shl) {
- Int32BinopMatcher mright(right);
- inputs[input_count++] = g.UseRegister(mright.left().node());
- if (mright.right().IsInRange(0, 31)) {
- opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
- inputs[input_count++] = g.UseImmediate(mright.right().node());
- } else {
- opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_R);
- inputs[input_count++] = g.UseRegister(mright.right().node());
- }
- } else if (right->opcode() == IrOpcode::kWord32Shr) {
- Int32BinopMatcher mright(right);
- inputs[input_count++] = g.UseRegister(mright.left().node());
- if (mright.right().IsInRange(1, 32)) {
- opcode |= AddressingModeField::encode(kMode_Operand2_R_LSR_I);
- inputs[input_count++] = g.UseImmediate(mright.right().node());
- } else {
- opcode |= AddressingModeField::encode(kMode_Operand2_R_LSR_R);
- inputs[input_count++] = g.UseRegister(mright.right().node());
- }
+ if (node->opcode() != IrOpcode::kWord32Or) return false;
+ Int32BinopMatcher m(node);
+ Node* shl = m.left().node();
+ Node* shr = m.right().node();
+ if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
+ std::swap(shl, shr);
+ } else if (!m.left().IsWord32Shl() || !m.right().IsWord32Shr()) {
+ return false;
+ }
+ Int32BinopMatcher mshr(shr);
+ Int32BinopMatcher mshl(shl);
+ Node* value = mshr.left().node();
+ if (value != mshl.left().node()) return false;
+ Node* shift = mshr.right().node();
+ Int32Matcher mshift(shift);
+ if (mshift.IsInRange(1, 31) && mshl.right().Is(32 - mshift.Value())) {
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_I);
+ *value_return = g.UseRegister(value);
+ *shift_return = g.UseImmediate(shift);
+ return true;
+ }
+ if (mshl.right().IsInt32Sub()) {
+ Int32BinopMatcher mshlright(mshl.right().node());
+ if (!mshlright.left().Is(32)) return false;
+ if (mshlright.right().node() != shift) return false;
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_R);
+ *value_return = g.UseRegister(value);
+ *shift_return = g.UseRegister(shift);
+ return true;
+ }
+ return false;
+}
+
+
+static inline bool TryMatchASR(InstructionSelector* selector,
+ InstructionCode* opcode_return, Node* node,
+ InstructionOperand** value_return,
+ InstructionOperand** shift_return) {
+ ArmOperandGenerator g(selector);
+ if (node->opcode() != IrOpcode::kWord32Sar) return false;
+ Int32BinopMatcher m(node);
+ *value_return = g.UseRegister(m.left().node());
+ if (m.right().IsInRange(1, 32)) {
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_I);
+ *shift_return = g.UseImmediate(m.right().node());
} else {
- opcode |= AddressingModeField::encode(kMode_Operand2_R);
- inputs[input_count++] = g.UseRegister(right);
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_R);
+ *shift_return = g.UseRegister(m.right().node());
}
+ return true;
+}
+
- // Append the optional labels.
- while (label_count-- != 0) {
- inputs[input_count++] = *labels++;
+static inline bool TryMatchLSL(InstructionSelector* selector,
+ InstructionCode* opcode_return, Node* node,
+ InstructionOperand** value_return,
+ InstructionOperand** shift_return) {
+ ArmOperandGenerator g(selector);
+ if (node->opcode() != IrOpcode::kWord32Shl) return false;
+ Int32BinopMatcher m(node);
+ *value_return = g.UseRegister(m.left().node());
+ if (m.right().IsInRange(0, 31)) {
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
+ *shift_return = g.UseImmediate(m.right().node());
+ } else {
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_R);
+ *shift_return = g.UseRegister(m.right().node());
}
+ return true;
+}
- ASSERT_NE(0, input_count);
- ASSERT_GE(ARRAY_SIZE(inputs), input_count);
- ASSERT_NE(kMode_None, AddressingModeField::decode(opcode));
- return selector->Emit(opcode, output_count, outputs, input_count, inputs);
+static inline bool TryMatchLSR(InstructionSelector* selector,
+ InstructionCode* opcode_return, Node* node,
+ InstructionOperand** value_return,
+ InstructionOperand** shift_return) {
+ ArmOperandGenerator g(selector);
+ if (node->opcode() != IrOpcode::kWord32Shr) return false;
+ Int32BinopMatcher m(node);
+ *value_return = g.UseRegister(m.left().node());
+ if (m.right().IsInRange(1, 32)) {
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_I);
+ *shift_return = g.UseImmediate(m.right().node());
+ } else {
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_R);
+ *shift_return = g.UseRegister(m.right().node());
+ }
+ return true;
}
-static Instruction* EmitBinop(InstructionSelector* selector,
- InstructionCode opcode, Node* node, Node* left,
- Node* right) {
+static inline bool TryMatchImmediateOrShift(InstructionSelector* selector,
+ InstructionCode* opcode_return,
+ Node* node,
+ size_t* input_count_return,
+ InstructionOperand** inputs) {
ArmOperandGenerator g(selector);
- InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
- const size_t output_count = ARRAY_SIZE(outputs);
- return EmitBinop(selector, opcode, output_count, outputs, left, right, 0,
- NULL);
+ if (g.CanBeImmediate(node, *opcode_return)) {
+ *opcode_return |= AddressingModeField::encode(kMode_Operand2_I);
+ inputs[0] = g.UseImmediate(node);
+ *input_count_return = 1;
+ return true;
+ }
+ if (TryMatchASR(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
+ TryMatchLSL(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
+ TryMatchLSR(selector, opcode_return, node, &inputs[0], &inputs[1]) ||
+ TryMatchROR(selector, opcode_return, node, &inputs[0], &inputs[1])) {
+ *input_count_return = 2;
+ return true;
+ }
+ return false;
}
@@ -198,17 +245,32 @@ static void VisitBinop(InstructionSelector* selector, Node* node,
InstructionCode opcode, InstructionCode reverse_opcode) {
ArmOperandGenerator g(selector);
Int32BinopMatcher m(node);
+ InstructionOperand* inputs[3];
+ size_t input_count = 0;
- Node* left = m.left().node();
- Node* right = m.right().node();
- if (g.CanBeImmediate(m.left().node(), reverse_opcode) ||
- m.left().IsWord32Sar() || m.left().IsWord32Shl() ||
- m.left().IsWord32Shr()) {
+ if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
+ &input_count, &inputs[1])) {
+ inputs[0] = g.UseRegister(m.left().node());
+ input_count++;
+ } else if (TryMatchImmediateOrShift(selector, &reverse_opcode,
+ m.left().node(), &input_count,
+ &inputs[1])) {
+ inputs[0] = g.UseRegister(m.right().node());
opcode = reverse_opcode;
- std::swap(left, right);
+ input_count++;
+ } else {
+ opcode |= AddressingModeField::encode(kMode_Operand2_R);
+ inputs[input_count++] = g.UseRegister(m.left().node());
+ inputs[input_count++] = g.UseRegister(m.right().node());
}
- EmitBinop(selector, opcode, node, left, right);
+ ASSERT_NE(0, input_count);
+ ASSERT_GE(ARRAY_SIZE(inputs), input_count);
+ ASSERT_NE(kMode_None, AddressingModeField::decode(opcode));
+
+ InstructionOperand* outputs[1] = {g.DefineAsRegister(node)};
+ const size_t output_count = ARRAY_SIZE(outputs);
+ selector->Emit(opcode, output_count, outputs, input_count, inputs);
}
@@ -311,20 +373,44 @@ void InstructionSelector::VisitStore(Node* node) {
}
+static inline void EmitBic(InstructionSelector* selector, Node* node,
+ Node* left, Node* right) {
+ ArmOperandGenerator g(selector);
+ InstructionCode opcode = kArmBic;
+ InstructionOperand* inputs[3];
+ size_t input_count = 0;
+ InstructionOperand* outputs[1] = {g.DefineAsRegister(node)};
+ const size_t output_count = ARRAY_SIZE(outputs);
+
+ inputs[input_count++] = g.UseRegister(left);
+ if (!TryMatchImmediateOrShift(selector, &opcode, right, &input_count,
+ &inputs[input_count])) {
+ opcode |= AddressingModeField::encode(kMode_Operand2_R);
+ inputs[input_count++] = g.UseRegister(right);
+ }
+
+ ASSERT_NE(0, input_count);
+ ASSERT_GE(ARRAY_SIZE(inputs), input_count);
+ ASSERT_NE(kMode_None, AddressingModeField::decode(opcode));
+
+ selector->Emit(opcode, output_count, outputs, input_count, inputs);
+}
+
+
void InstructionSelector::VisitWord32And(Node* node) {
ArmOperandGenerator g(this);
Int32BinopMatcher m(node);
if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) {
Int32BinopMatcher mleft(m.left().node());
if (mleft.right().Is(-1)) {
- EmitBinop(this, kArmBic, node, m.right().node(), mleft.left().node());
+ EmitBic(this, node, m.right().node(), mleft.left().node());
return;
}
}
if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) {
Int32BinopMatcher mright(m.right().node());
if (mright.right().Is(-1)) {
- EmitBinop(this, kArmBic, node, m.left().node(), mright.left().node());
+ EmitBic(this, node, m.left().node(), mright.left().node());
return;
}
}
@@ -362,6 +448,14 @@ void InstructionSelector::VisitWord32And(Node* node) {
void InstructionSelector::VisitWord32Or(Node* node) {
+ ArmOperandGenerator g(this);
+ InstructionCode opcode = kArmMov;
+ InstructionOperand* value_operand;
+ InstructionOperand* shift_operand;
+ if (TryMatchROR(this, &opcode, node, &value_operand, &shift_operand)) {
+ Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand);
+ return;
+ }
VisitBinop(this, node, kArmOrr, kArmOrr);
}
@@ -378,18 +472,22 @@ void InstructionSelector::VisitWord32Xor(Node* node) {
}
+template <typename TryMatchShift>
+static inline void VisitShift(InstructionSelector* selector, Node* node,
+ TryMatchShift try_match_shift) {
+ ArmOperandGenerator g(selector);
+ InstructionCode opcode = kArmMov;
+ InstructionOperand* value_operand = NULL;
+ InstructionOperand* shift_operand = NULL;
+ CHECK(
+ try_match_shift(selector, &opcode, node, &value_operand, &shift_operand));
+ selector->Emit(opcode, g.DefineAsRegister(node), value_operand,
+ shift_operand);
+}
+
+
void InstructionSelector::VisitWord32Shl(Node* node) {
- ArmOperandGenerator g(this);
- Int32BinopMatcher m(node);
- if (m.right().IsInRange(0, 31)) {
- Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
- g.DefineAsRegister(node), g.UseRegister(m.left().node()),
- g.UseImmediate(m.right().node()));
- } else {
- Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_LSL_R),
- g.DefineAsRegister(node), g.UseRegister(m.left().node()),
- g.UseRegister(m.right().node()));
- }
+ VisitShift(this, node, TryMatchLSL);
}
@@ -413,30 +511,12 @@ void InstructionSelector::VisitWord32Shr(Node* node) {
}
}
}
- if (m.right().IsInRange(1, 32)) {
- Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_LSR_I),
- g.DefineAsRegister(node), g.UseRegister(m.left().node()),
- g.UseImmediate(m.right().node()));
- return;
- }
- Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_LSR_R),
- g.DefineAsRegister(node), g.UseRegister(m.left().node()),
- g.UseRegister(m.right().node()));
+ VisitShift(this, node, TryMatchLSR);
}
void InstructionSelector::VisitWord32Sar(Node* node) {
- ArmOperandGenerator g(this);
- Int32BinopMatcher m(node);
- if (m.right().IsInRange(1, 32)) {
- Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_ASR_I),
- g.DefineAsRegister(node), g.UseRegister(m.left().node()),
- g.UseImmediate(m.right().node()));
- } else {
- Emit(kArmMov | AddressingModeField::encode(kMode_Operand2_R_ASR_R),
- g.DefineAsRegister(node), g.UseRegister(m.left().node()),
- g.UseRegister(m.right().node()));
- }
+ VisitShift(this, node, TryMatchASR);
}
@@ -711,31 +791,44 @@ static void VisitWordCompare(InstructionSelector* selector, Node* node,
bool commutative, bool requires_output) {
ArmOperandGenerator g(selector);
Int32BinopMatcher m(node);
-
- Node* left = m.left().node();
- Node* right = m.right().node();
- if (g.CanBeImmediate(m.left().node(), opcode) || m.left().IsWord32Sar() ||
- m.left().IsWord32Shl() || m.left().IsWord32Shr()) {
+ InstructionOperand* inputs[5];
+ size_t input_count = 0;
+ InstructionOperand* outputs[1];
+ size_t output_count = 0;
+
+ if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
+ &input_count, &inputs[1])) {
+ inputs[0] = g.UseRegister(m.left().node());
+ input_count++;
+ } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
+ &input_count, &inputs[1])) {
if (!commutative) cont->Commute();
- std::swap(left, right);
+ inputs[0] = g.UseRegister(m.right().node());
+ input_count++;
+ } else {
+ opcode |= AddressingModeField::encode(kMode_Operand2_R);
+ inputs[input_count++] = g.UseRegister(m.left().node());
+ inputs[input_count++] = g.UseRegister(m.right().node());
}
- opcode = cont->Encode(opcode);
if (cont->IsBranch()) {
- InstructionOperand* outputs[1];
- size_t output_count = 0;
if (requires_output) {
outputs[output_count++] = g.DefineAsRegister(node);
}
- InstructionOperand* labels[] = {g.Label(cont->true_block()),
- g.Label(cont->false_block())};
- const size_t label_count = ARRAY_SIZE(labels);
- EmitBinop(selector, opcode, output_count, outputs, left, right, label_count,
- labels)->MarkAsControl();
+ inputs[input_count++] = g.Label(cont->true_block());
+ inputs[input_count++] = g.Label(cont->false_block());
} else {
ASSERT(cont->IsSet());
- EmitBinop(selector, opcode, cont->result(), left, right);
+ outputs[output_count++] = g.DefineAsRegister(cont->result());
}
+
+ ASSERT_NE(0, input_count);
+ ASSERT_GE(ARRAY_SIZE(inputs), input_count);
+ ASSERT_GE(ARRAY_SIZE(outputs), output_count);
+
+ Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
+ outputs, input_count, inputs);
+ if (cont->IsBranch()) instr->MarkAsControl();
}
« 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