Revision: 22732
Author: [email protected]
Date: Thu Jul 31 07:44:29 2014 UTC
Log: [arm] Add support for ROR. Refactor operand2 handling.
This was the last missing bit for full "flexible second operand" /
operand2 support on ARM.
TEST=cctest/test-instruction-selector-arm,cctest/test-run-machops
[email protected]
Review URL: https://codereview.chromium.org/434553002
http://code.google.com/p/v8/source/detail?r=22732
Modified:
/branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc
/branches/bleeding_edge/src/compiler/arm/instruction-codes-arm.h
/branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
/branches/bleeding_edge/test/cctest/compiler/codegen-tester.h
/branches/bleeding_edge/test/cctest/compiler/test-instruction-selector-arm.cc
/branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc
/branches/bleeding_edge/test/cctest/compiler/value-helper.h
=======================================
--- /branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc Wed Jul
30 13:54:45 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc Thu Jul
31 07:44:29 2014 UTC
@@ -79,6 +79,10 @@
return Operand(InputRegister(index + 0), LSR, InputInt5(index +
1));
case kMode_Operand2_R_LSR_R:
return Operand(InputRegister(index + 0), LSR, InputRegister(index
+ 1));
+ case kMode_Operand2_R_ROR_I:
+ return Operand(InputRegister(index + 0), ROR, InputInt5(index +
1));
+ case kMode_Operand2_R_ROR_R:
+ return Operand(InputRegister(index + 0), ROR, InputRegister(index
+ 1));
}
UNREACHABLE();
return Operand::Zero();
@@ -96,6 +100,8 @@
case kMode_Operand2_R_LSL_R:
case kMode_Operand2_R_LSR_I:
case kMode_Operand2_R_LSR_R:
+ case kMode_Operand2_R_ROR_I:
+ case kMode_Operand2_R_ROR_R:
break;
case kMode_Offset_RI:
*first_index += 2;
=======================================
--- /branches/bleeding_edge/src/compiler/arm/instruction-codes-arm.h Wed
Jul 30 13:54:45 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/instruction-codes-arm.h Thu
Jul 31 07:44:29 2014 UTC
@@ -73,9 +73,11 @@
V(Operand2_R_ASR_I) /* %r0 ASR K */ \
V(Operand2_R_LSL_I) /* %r0 LSL K */ \
V(Operand2_R_LSR_I) /* %r0 LSR K */ \
+ V(Operand2_R_ROR_I) /* %r0 ROR K */ \
V(Operand2_R_ASR_R) /* %r0 ASR %r1 */ \
V(Operand2_R_LSL_R) /* %r0 LSL %r1 */ \
- V(Operand2_R_LSR_R) /* %r0 LSR %r1 */
+ V(Operand2_R_LSR_R) /* %r0 LSR %r1 */ \
+ V(Operand2_R_ROR_R) /* %r0 ROR %r1 */
} // namespace compiler
} // namespace internal
=======================================
--- /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Wed Jul 30 13:54:45 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Thu Jul 31 07:44:29 2014 UTC
@@ -121,75 +121,122 @@
}
-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;
+ 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;
+}
- 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());
- }
+
+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 @@
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);
}
@@ -309,6 +371,30 @@
g.UseRegister(base), g.UseRegister(index), val);
}
}
+
+
+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) {
@@ -317,14 +403,14 @@
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::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);
}
@@ -376,20 +470,24 @@
VisitBinop(this, node, kArmEor, kArmEor);
}
}
+
+
+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 @@
}
}
}
- 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 @@
bool commutative, bool requires_output) {
ArmOperandGenerator g(selector);
Int32BinopMatcher m(node);
+ InstructionOperand* inputs[5];
+ size_t input_count = 0;
+ InstructionOperand* outputs[1];
+ size_t output_count = 0;
- 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()) {
+ 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();
}
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/codegen-tester.h Wed Jul
30 15:34:09 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/codegen-tester.h Thu Jul
31 07:44:29 2014 UTC
@@ -101,6 +101,25 @@
: MachineAssemblerTester<RawMachineAssembler>(
ReturnValueTraits<ReturnType>::Representation(), p0, p1, p2,
p3,
p4) {}
+
+ template <typename Ci, typename Fn>
+ void Run(const Ci& ci, const Fn& fn) {
+ typename Ci::const_iterator i;
+ for (i = ci.begin(); i != ci.end(); ++i) {
+ CHECK_EQ(fn(*i), this->Call(*i));
+ }
+ }
+
+ template <typename Ci, typename Cj, typename Fn>
+ void Run(const Ci& ci, const Cj& cj, const Fn& fn) {
+ typename Ci::const_iterator i;
+ typename Cj::const_iterator j;
+ for (i = ci.begin(); i != ci.end(); ++i) {
+ for (j = cj.begin(); j != cj.end(); ++j) {
+ CHECK_EQ(fn(*i, *j), this->Call(*i, *j));
+ }
+ }
+ }
};
@@ -162,6 +181,17 @@
T->Return(val);
}
}
+
+ template <typename Ci, typename Cj, typename Fn>
+ void Run(const Ci& ci, const Cj& cj, const Fn& fn) {
+ typename Ci::const_iterator i;
+ typename Cj::const_iterator j;
+ for (i = ci.begin(); i != ci.end(); ++i) {
+ for (j = cj.begin(); j != cj.end(); ++j) {
+ CHECK_EQ(fn(*i, *j), this->call(*i, *j));
+ }
+ }
+ }
protected:
CType p0;
=======================================
---
/branches/bleeding_edge/test/cctest/compiler/test-instruction-selector-arm.cc
Wed Jul 30 13:54:45 2014 UTC
+++
/branches/bleeding_edge/test/cctest/compiler/test-instruction-selector-arm.cc
Thu Jul 31 07:44:29 2014 UTC
@@ -5,6 +5,7 @@
#include <list>
#include "test/cctest/compiler/instruction-selector-tester.h"
+#include "test/cctest/compiler/value-helper.h"
using namespace v8::internal;
using namespace v8::internal::compiler;
@@ -128,6 +129,66 @@
}
}
}
+
+
+TEST(InstructionSelectorDPIAndRotateRightP) {
+ DPIs dpis;
+ for (DPIs::const_iterator i = dpis.begin(); i != dpis.end(); ++i) {
+ DPI dpi = *i;
+ {
+ InstructionSelectorTester m;
+ Node* value = m.Parameter(1);
+ Node* shift = m.Parameter(2);
+ Node* ror = m.Word32Or(
+ m.Word32Shr(value, shift),
+ m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32), shift)));
+ m.Return(m.NewNode(dpi.op, m.Parameter(0), ror));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(dpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ }
+ {
+ InstructionSelectorTester m;
+ Node* value = m.Parameter(1);
+ Node* shift = m.Parameter(2);
+ Node* ror =
+ m.Word32Or(m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32),
shift)),
+ m.Word32Shr(value, shift));
+ m.Return(m.NewNode(dpi.op, m.Parameter(0), ror));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(dpi.arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ }
+ {
+ InstructionSelectorTester m;
+ Node* value = m.Parameter(1);
+ Node* shift = m.Parameter(2);
+ Node* ror = m.Word32Or(
+ m.Word32Shr(value, shift),
+ m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32), shift)));
+ m.Return(m.NewNode(dpi.op, ror, m.Parameter(0)));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(dpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ }
+ {
+ InstructionSelectorTester m;
+ Node* value = m.Parameter(1);
+ Node* shift = m.Parameter(2);
+ Node* ror =
+ m.Word32Or(m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32),
shift)),
+ m.Word32Shr(value, shift));
+ m.Return(m.NewNode(dpi.op, ror, m.Parameter(0)));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(dpi.reverse_arch_opcode, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ }
+ }
+}
TEST(InstructionSelectorDPIAndShiftImm) {
@@ -222,6 +283,100 @@
CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
}
}
+
+
+TEST(InstructionSelectorShiftP) {
+ Shifts shifts;
+ for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
+ Shift shift = *i;
+ InstructionSelectorTester m;
+ m.Return(m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmMov, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ }
+}
+
+
+TEST(InstructionSelectorShiftImm) {
+ Shifts shifts;
+ for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
+ Shift shift = *i;
+ for (int32_t imm = shift.i_low; imm <= shift.i_high; ++imm) {
+ InstructionSelectorTester m;
+ m.Return(m.NewNode(shift.op, m.Parameter(0), m.Int32Constant(imm)));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmMov, m.code[0]->arch_opcode());
+ CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(imm, m.ToInt32(m.code[0]->InputAt(1)));
+ }
+ }
+}
+
+
+TEST(InstructionSelectorRotateRightP) {
+ {
+ InstructionSelectorTester m;
+ Node* value = m.Parameter(0);
+ Node* shift = m.Parameter(1);
+ m.Return(
+ m.Word32Or(m.Word32Shr(value, shift),
+ m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32),
shift))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmMov, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ }
+ {
+ InstructionSelectorTester m;
+ Node* value = m.Parameter(0);
+ Node* shift = m.Parameter(1);
+ m.Return(
+ m.Word32Or(m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32),
shift)),
+ m.Word32Shr(value, shift)));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmMov, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ }
+}
+
+
+TEST(InstructionSelectorRotateRightImm) {
+ FOR_INPUTS(uint32_t, ror, i) {
+ uint32_t shift = *i;
+ {
+ InstructionSelectorTester m;
+ Node* value = m.Parameter(0);
+ m.Return(m.Word32Or(m.Word32Shr(value, m.Int32Constant(shift)),
+ m.Word32Shl(value, m.Int32Constant(32 -
shift))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmMov, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_I, m.code[0]->addressing_mode());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(shift, m.ToInt32(m.code[0]->InputAt(1)));
+ }
+ {
+ InstructionSelectorTester m;
+ Node* value = m.Parameter(0);
+ m.Return(m.Word32Or(m.Word32Shl(value, m.Int32Constant(32 - shift)),
+ m.Word32Shr(value, m.Int32Constant(shift))));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmMov, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_I, m.code[0]->addressing_mode());
+ CHECK_EQ(2, m.code[0]->InputCount());
+ CHECK_EQ(shift, m.ToInt32(m.code[0]->InputAt(1)));
+ }
+ }
+}
TEST(InstructionSelectorInt32MulP) {
@@ -917,6 +1072,185 @@
}
}
}
+
+
+TEST(InstructionSelectorBranchWithWord32EqualAndRotateRightP) {
+ {
+ InstructionSelectorTester m;
+ MLabel blocka, blockb;
+ Node* input = m.Parameter(0);
+ Node* value = m.Parameter(1);
+ Node* shift = m.Parameter(2);
+ Node* ror =
+ m.Word32Or(m.Word32Shr(value, shift),
+ m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32),
shift)));
+ m.Branch(m.Word32Equal(input, ror), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(0));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
+ CHECK_EQ(kEqual, m.code[0]->flags_condition());
+ }
+ {
+ InstructionSelectorTester m;
+ MLabel blocka, blockb;
+ Node* input = m.Parameter(0);
+ Node* value = m.Parameter(1);
+ Node* shift = m.Parameter(2);
+ Node* ror =
+ m.Word32Or(m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32),
shift)),
+ m.Word32Shr(value, shift));
+ m.Branch(m.Word32Equal(input, ror), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(0));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
+ CHECK_EQ(kEqual, m.code[0]->flags_condition());
+ }
+ {
+ InstructionSelectorTester m;
+ MLabel blocka, blockb;
+ Node* input = m.Parameter(0);
+ Node* value = m.Parameter(1);
+ Node* shift = m.Parameter(2);
+ Node* ror =
+ m.Word32Or(m.Word32Shr(value, shift),
+ m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32),
shift)));
+ m.Branch(m.Word32Equal(ror, input), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(0));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
+ CHECK_EQ(kEqual, m.code[0]->flags_condition());
+ }
+ {
+ InstructionSelectorTester m;
+ MLabel blocka, blockb;
+ Node* input = m.Parameter(0);
+ Node* value = m.Parameter(1);
+ Node* shift = m.Parameter(2);
+ Node* ror =
+ m.Word32Or(m.Word32Shl(value, m.Int32Sub(m.Int32Constant(32),
shift)),
+ m.Word32Shr(value, shift));
+ m.Branch(m.Word32Equal(ror, input), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(0));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_R, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
+ CHECK_EQ(kEqual, m.code[0]->flags_condition());
+ }
+}
+
+
+TEST(InstructionSelectorBranchWithWord32EqualAndRotateRightImm) {
+ FOR_INPUTS(uint32_t, ror, i) {
+ uint32_t shift = *i;
+ {
+ InstructionSelectorTester m;
+ MLabel blocka, blockb;
+ Node* input = m.Parameter(0);
+ Node* value = m.Parameter(1);
+ Node* ror = m.Word32Or(m.Word32Shr(value, m.Int32Constant(shift)),
+ m.Word32Shl(value, m.Int32Constant(32 -
shift)));
+ m.Branch(m.Word32Equal(input, ror), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(0));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
+ CHECK_EQ(kEqual, m.code[0]->flags_condition());
+ CHECK_LE(3, m.code[0]->InputCount());
+ CHECK_EQ(shift, m.ToInt32(m.code[0]->InputAt(2)));
+ }
+ {
+ InstructionSelectorTester m;
+ MLabel blocka, blockb;
+ Node* input = m.Parameter(0);
+ Node* value = m.Parameter(1);
+ Node* ror = m.Word32Or(m.Word32Shl(value, m.Int32Constant(32 -
shift)),
+ m.Word32Shr(value, m.Int32Constant(shift)));
+ m.Branch(m.Word32Equal(input, ror), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(0));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
+ CHECK_EQ(kEqual, m.code[0]->flags_condition());
+ CHECK_LE(3, m.code[0]->InputCount());
+ CHECK_EQ(shift, m.ToInt32(m.code[0]->InputAt(2)));
+ }
+ {
+ InstructionSelectorTester m;
+ MLabel blocka, blockb;
+ Node* input = m.Parameter(0);
+ Node* value = m.Parameter(1);
+ Node* ror = m.Word32Or(m.Word32Shr(value, m.Int32Constant(shift)),
+ m.Word32Shl(value, m.Int32Constant(32 -
shift)));
+ m.Branch(m.Word32Equal(ror, input), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(0));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
+ CHECK_EQ(kEqual, m.code[0]->flags_condition());
+ CHECK_LE(3, m.code[0]->InputCount());
+ CHECK_EQ(shift, m.ToInt32(m.code[0]->InputAt(2)));
+ }
+ {
+ InstructionSelectorTester m;
+ MLabel blocka, blockb;
+ Node* input = m.Parameter(0);
+ Node* value = m.Parameter(1);
+ Node* ror = m.Word32Or(m.Word32Shl(value, m.Int32Constant(32 -
shift)),
+ m.Word32Shr(value, m.Int32Constant(shift)));
+ m.Branch(m.Word32Equal(ror, input), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(0));
+ m.SelectInstructions();
+ CHECK_EQ(1, m.code.size());
+ CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
+ CHECK_EQ(kMode_Operand2_R_ROR_I, m.code[0]->addressing_mode());
+ CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
+ CHECK_EQ(kEqual, m.code[0]->flags_condition());
+ CHECK_LE(3, m.code[0]->InputCount());
+ CHECK_EQ(shift, m.ToInt32(m.code[0]->InputAt(2)));
+ }
+ }
+}
TEST(InstructionSelectorBranchWithDPIP) {
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Wed
Jul 30 16:21:36 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Thu
Jul 31 07:44:29 2014 UTC
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <functional>
#include <limits>
-#include "src/v8.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
@@ -3678,6 +3678,53 @@
CHECK_EQ(kInputSize - i - 1, outputs[i]);
}
}
+
+
+static inline uint32_t rotr32(uint32_t i, uint32_t j) {
+ return (i >> j) | (i << (32 - j));
+}
+
+
+TEST(RunTestInt32RotateRightP) {
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Int32BinopTester bt(&m);
+ bt.AddReturn(m.Word32Or(
+ m.Word32Shr(bt.param0, bt.param1),
+ m.Word32Shl(bt.param0, m.Int32Sub(m.Int32Constant(32),
bt.param1))));
+ bt.Run(ValueHelper::uint32_vector(), ValueHelper::ror_vector(),
rotr32);
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m;
+ Int32BinopTester bt(&m);
+ bt.AddReturn(m.Word32Or(
+ m.Word32Shl(bt.param0, m.Int32Sub(m.Int32Constant(32), bt.param1)),
+ m.Word32Shr(bt.param0, bt.param1)));
+ bt.Run(ValueHelper::uint32_vector(), ValueHelper::ror_vector(),
rotr32);
+ }
+}
+
+
+TEST(RunTestInt32RotateRightImm) {
+ FOR_INPUTS(uint32_t, ror, i) {
+ {
+ RawMachineAssemblerTester<int32_t> m(kMachineWord32);
+ Node* value = m.Parameter(0);
+ m.Return(m.Word32Or(m.Word32Shr(value, m.Int32Constant(*i)),
+ m.Word32Shl(value, m.Int32Constant(32 - *i))));
+ m.Run(ValueHelper::uint32_vector(),
+ std::bind2nd(std::ptr_fun(&rotr32), *i));
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m(kMachineWord32);
+ Node* value = m.Parameter(0);
+ m.Return(m.Word32Or(m.Word32Shl(value, m.Int32Constant(32 - *i)),
+ m.Word32Shr(value, m.Int32Constant(*i))));
+ m.Run(ValueHelper::uint32_vector(),
+ std::bind2nd(std::ptr_fun(&rotr32), *i));
+ }
+ }
+}
TEST(RunSpillLotsOfThings) {
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/value-helper.h Wed Jul 30
14:40:57 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/value-helper.h Thu Jul 31
07:44:29 2014 UTC
@@ -104,6 +104,13 @@
V8_INFINITY * 0.0, nan};
return std::vector<double>(&values[0], &values[ARRAY_SIZE(values)]);
}
+
+ static const std::vector<uint32_t> ror_vector() {
+ static const uint32_t kValues[31] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
+ return std::vector<uint32_t>(&kValues[0],
&kValues[ARRAY_SIZE(kValues)]);
+ }
};
// Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... }
@@ -116,8 +123,9 @@
#define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var)
#define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var)
#define FOR_FLOAT64_INPUTS(var) FOR_INPUTS(double, float64, var)
-}
-}
-} // namespace v8::internal::compiler
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
#endif // V8_CCTEST_COMPILER_VALUE_HELPER_H_
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.