Commit f173937c authored by Daniel Clifford's avatar Daniel Clifford

Generalize ScaledWithOffsetMatcher to support 64 bits

Preparation for supporting more addressing modes in instruction selection.

R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/729853005

Cr-Commit-Position: refs/heads/master@{#25373}
parent e9a3d153
...@@ -39,8 +39,11 @@ struct NodeMatcher { ...@@ -39,8 +39,11 @@ struct NodeMatcher {
// A pattern matcher for abitrary value constants. // A pattern matcher for abitrary value constants.
template <typename T, IrOpcode::Value kOpcode> template <typename T, IrOpcode::Value kMatchOpcode>
struct ValueMatcher : public NodeMatcher { struct ValueMatcher : public NodeMatcher {
typedef T ValueType;
static const IrOpcode::Value kOpcode = kMatchOpcode;
explicit ValueMatcher(Node* node) explicit ValueMatcher(Node* node)
: NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) { : NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) {
if (has_value_) { if (has_value_) {
...@@ -124,6 +127,9 @@ struct BinopMatcher : public NodeMatcher { ...@@ -124,6 +127,9 @@ struct BinopMatcher : public NodeMatcher {
if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); if (HasProperty(Operator::kCommutative)) PutConstantOnRight();
} }
typedef Left LeftMatcher;
typedef Right RightMatcher;
const Left& left() const { return left_; } const Left& left() const { return left_; }
const Right& right() const { return right_; } const Right& right() const { return right_; }
...@@ -157,16 +163,19 @@ typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; ...@@ -157,16 +163,19 @@ typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher;
typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher;
struct Int32AddMatcher : public Int32BinopMatcher { template <class BinopMatcher, IrOpcode::Value kAddOpcode,
explicit Int32AddMatcher(Node* node) IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode>
: Int32BinopMatcher(node), scale_exponent_(-1) { struct AddMatcher : public BinopMatcher {
PutScaledInputOnLeft(); static const IrOpcode::Value kOpcode = kAddOpcode;
explicit AddMatcher(Node* node) : BinopMatcher(node), scale_exponent_(-1) {
if (this->HasProperty(Operator::kCommutative)) PutScaledInputOnLeft();
} }
bool HasScaledInput() const { return scale_exponent_ != -1; } bool HasScaledInput() const { return scale_exponent_ != -1; }
Node* ScaledInput() const { Node* ScaledInput() const {
DCHECK(HasScaledInput()); DCHECK(HasScaledInput());
return left().node()->InputAt(0); return this->left().node()->InputAt(0);
} }
int ScaleExponent() const { int ScaleExponent() const {
DCHECK(HasScaledInput()); DCHECK(HasScaledInput());
...@@ -175,18 +184,20 @@ struct Int32AddMatcher : public Int32BinopMatcher { ...@@ -175,18 +184,20 @@ struct Int32AddMatcher : public Int32BinopMatcher {
private: private:
int GetInputScaleExponent(Node* node) const { int GetInputScaleExponent(Node* node) const {
if (node->opcode() == IrOpcode::kWord32Shl) { if (node->opcode() == kShiftOpcode) {
Int32BinopMatcher m(node); BinopMatcher m(node);
if (m.right().HasValue()) { if (m.right().HasValue()) {
int32_t value = m.right().Value(); typename BinopMatcher::RightMatcher::ValueType value =
m.right().Value();
if (value >= 0 && value <= 3) { if (value >= 0 && value <= 3) {
return value; return value;
} }
} }
} else if (node->opcode() == IrOpcode::kInt32Mul) { } else if (node->opcode() == kMulOpcode) {
Int32BinopMatcher m(node); BinopMatcher m(node);
if (m.right().HasValue()) { if (m.right().HasValue()) {
int32_t value = m.right().Value(); typename BinopMatcher::RightMatcher::ValueType value =
m.right().Value();
if (value == 1) { if (value == 1) {
return 0; return 0;
} else if (value == 2) { } else if (value == 2) {
...@@ -202,20 +213,20 @@ struct Int32AddMatcher : public Int32BinopMatcher { ...@@ -202,20 +213,20 @@ struct Int32AddMatcher : public Int32BinopMatcher {
} }
void PutScaledInputOnLeft() { void PutScaledInputOnLeft() {
scale_exponent_ = GetInputScaleExponent(right().node()); scale_exponent_ = GetInputScaleExponent(this->right().node());
if (scale_exponent_ >= 0) { if (scale_exponent_ >= 0) {
int left_scale_exponent = GetInputScaleExponent(left().node()); int left_scale_exponent = GetInputScaleExponent(this->left().node());
if (left_scale_exponent == -1) { if (left_scale_exponent == -1) {
SwapInputs(); this->SwapInputs();
} else { } else {
scale_exponent_ = left_scale_exponent; scale_exponent_ = left_scale_exponent;
} }
} else { } else {
scale_exponent_ = GetInputScaleExponent(left().node()); scale_exponent_ = GetInputScaleExponent(this->left().node());
if (scale_exponent_ == -1) { if (scale_exponent_ == -1) {
if (right().opcode() == IrOpcode::kInt32Add && if (this->right().opcode() == kAddOpcode &&
left().opcode() != IrOpcode::kInt32Add) { this->left().opcode() != kAddOpcode) {
SwapInputs(); this->SwapInputs();
} }
} }
} }
...@@ -224,6 +235,12 @@ struct Int32AddMatcher : public Int32BinopMatcher { ...@@ -224,6 +235,12 @@ struct Int32AddMatcher : public Int32BinopMatcher {
int scale_exponent_; int scale_exponent_;
}; };
typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Mul,
IrOpcode::kWord32Shl> Int32AddMatcher;
typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Mul,
IrOpcode::kWord64Shl> Int64AddMatcher;
template <class AddMatcher>
struct ScaledWithOffsetMatcher { struct ScaledWithOffsetMatcher {
explicit ScaledWithOffsetMatcher(Node* node) explicit ScaledWithOffsetMatcher(Node* node)
: matches_(false), : matches_(false),
...@@ -231,13 +248,12 @@ struct ScaledWithOffsetMatcher { ...@@ -231,13 +248,12 @@ struct ScaledWithOffsetMatcher {
scale_exponent_(0), scale_exponent_(0),
offset_(NULL), offset_(NULL),
constant_(NULL) { constant_(NULL) {
if (node->opcode() != IrOpcode::kInt32Add) return; // The ScaledWithOffsetMatcher canonicalizes the order of constants and
// scale factors that are used as inputs, so instead of enumerating all
// The Int32AddMatcher canonicalizes the order of constants and scale // possible patterns by brute force, checking for node clusters using the
// factors that are used as inputs, so instead of enumerating all possible // following templates in the following order suffices to find all of the
// patterns by brute force, checking for node clusters using the following // interesting cases (S = scaled input, O = offset input, C = constant
// templates in the following order suffices to find all of the interesting // input):
// cases (S = scaled input, O = offset input, C = constant input):
// (S + (O + C)) // (S + (O + C))
// (S + (O + O)) // (S + (O + O))
// (S + C) // (S + C)
...@@ -248,14 +264,15 @@ struct ScaledWithOffsetMatcher { ...@@ -248,14 +264,15 @@ struct ScaledWithOffsetMatcher {
// ((O + O) + C) // ((O + O) + C)
// (O + C) // (O + C)
// (O + O) // (O + O)
Int32AddMatcher base_matcher(node); if (node->InputCount() < 2) return;
AddMatcher base_matcher(node);
Node* left = base_matcher.left().node(); Node* left = base_matcher.left().node();
Node* right = base_matcher.right().node(); Node* right = base_matcher.right().node();
if (base_matcher.HasScaledInput() && left->OwnedBy(node)) { if (base_matcher.HasScaledInput() && left->OwnedBy(node)) {
scaled_ = base_matcher.ScaledInput(); scaled_ = base_matcher.ScaledInput();
scale_exponent_ = base_matcher.ScaleExponent(); scale_exponent_ = base_matcher.ScaleExponent();
if (right->opcode() == IrOpcode::kInt32Add && right->OwnedBy(node)) { if (right->opcode() == AddMatcher::kOpcode && right->OwnedBy(node)) {
Int32AddMatcher right_matcher(right); AddMatcher right_matcher(right);
if (right_matcher.right().HasValue()) { if (right_matcher.right().HasValue()) {
// (S + (O + C)) // (S + (O + C))
offset_ = right_matcher.left().node(); offset_ = right_matcher.left().node();
...@@ -272,8 +289,8 @@ struct ScaledWithOffsetMatcher { ...@@ -272,8 +289,8 @@ struct ScaledWithOffsetMatcher {
offset_ = right; offset_ = right;
} }
} else { } else {
if (left->opcode() == IrOpcode::kInt32Add && left->OwnedBy(node)) { if (left->opcode() == AddMatcher::kOpcode && left->OwnedBy(node)) {
Int32AddMatcher left_matcher(left); AddMatcher left_matcher(left);
Node* left_left = left_matcher.left().node(); Node* left_left = left_matcher.left().node();
Node* left_right = left_matcher.right().node(); Node* left_right = left_matcher.right().node();
if (left_matcher.HasScaledInput() && left_left->OwnedBy(left)) { if (left_matcher.HasScaledInput() && left_left->OwnedBy(left)) {
...@@ -321,6 +338,25 @@ struct ScaledWithOffsetMatcher { ...@@ -321,6 +338,25 @@ struct ScaledWithOffsetMatcher {
} }
} }
} }
int64_t value = 0;
if (constant_ != NULL) {
switch (constant_->opcode()) {
case IrOpcode::kInt32Constant: {
value = OpParameter<int32_t>(constant_);
break;
}
case IrOpcode::kInt64Constant: {
value = OpParameter<int64_t>(constant_);
break;
}
default:
UNREACHABLE();
break;
}
if (value == 0) {
constant_ = NULL;
}
}
matches_ = true; matches_ = true;
} }
...@@ -340,6 +376,9 @@ struct ScaledWithOffsetMatcher { ...@@ -340,6 +376,9 @@ struct ScaledWithOffsetMatcher {
Node* constant_; Node* constant_;
}; };
typedef ScaledWithOffsetMatcher<Int32AddMatcher> ScaledWithOffset32Matcher;
typedef ScaledWithOffsetMatcher<Int64AddMatcher> ScaledWithOffset64Matcher;
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -388,10 +388,13 @@ AddressingMode GenerateMemoryOperandInputs(X64OperandGenerator* g, Node* scaled, ...@@ -388,10 +388,13 @@ AddressingMode GenerateMemoryOperandInputs(X64OperandGenerator* g, Node* scaled,
mode = kMRn_modes[scale_exponent]; mode = kMRn_modes[scale_exponent];
} }
} else { } else {
DCHECK(constant != NULL); if (constant == NULL) {
mode = kMode_MR;
} else {
inputs[(*input_count)++] = g->UseImmediate(constant); inputs[(*input_count)++] = g->UseImmediate(constant);
mode = kMode_MRI; mode = kMode_MRI;
} }
}
} else { } else {
DCHECK(scaled != NULL); DCHECK(scaled != NULL);
DCHECK(scale_exponent >= 0 && scale_exponent <= 3); DCHECK(scale_exponent >= 0 && scale_exponent <= 3);
...@@ -415,7 +418,7 @@ AddressingMode GenerateMemoryOperandInputs(X64OperandGenerator* g, Node* scaled, ...@@ -415,7 +418,7 @@ AddressingMode GenerateMemoryOperandInputs(X64OperandGenerator* g, Node* scaled,
void InstructionSelector::VisitInt32Add(Node* node) { void InstructionSelector::VisitInt32Add(Node* node) {
// Try to match the Add to a leal pattern // Try to match the Add to a leal pattern
ScaledWithOffsetMatcher m(node); ScaledWithOffset32Matcher m(node);
X64OperandGenerator g(this); X64OperandGenerator g(this);
if (m.matches() && (m.constant() == NULL || g.CanBeImmediate(m.constant()))) { if (m.matches() && (m.constant() == NULL || g.CanBeImmediate(m.constant()))) {
InstructionOperand* inputs[4]; InstructionOperand* inputs[4];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment