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 {
// A pattern matcher for abitrary value constants.
template <typename T, IrOpcode::Value kOpcode>
template <typename T, IrOpcode::Value kMatchOpcode>
struct ValueMatcher : public NodeMatcher {
typedef T ValueType;
static const IrOpcode::Value kOpcode = kMatchOpcode;
explicit ValueMatcher(Node* node)
: NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) {
if (has_value_) {
......@@ -124,6 +127,9 @@ struct BinopMatcher : public NodeMatcher {
if (HasProperty(Operator::kCommutative)) PutConstantOnRight();
}
typedef Left LeftMatcher;
typedef Right RightMatcher;
const Left& left() const { return left_; }
const Right& right() const { return right_; }
......@@ -157,16 +163,19 @@ typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher;
typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher;
struct Int32AddMatcher : public Int32BinopMatcher {
explicit Int32AddMatcher(Node* node)
: Int32BinopMatcher(node), scale_exponent_(-1) {
PutScaledInputOnLeft();
template <class BinopMatcher, IrOpcode::Value kAddOpcode,
IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode>
struct AddMatcher : public BinopMatcher {
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; }
Node* ScaledInput() const {
DCHECK(HasScaledInput());
return left().node()->InputAt(0);
return this->left().node()->InputAt(0);
}
int ScaleExponent() const {
DCHECK(HasScaledInput());
......@@ -175,18 +184,20 @@ struct Int32AddMatcher : public Int32BinopMatcher {
private:
int GetInputScaleExponent(Node* node) const {
if (node->opcode() == IrOpcode::kWord32Shl) {
Int32BinopMatcher m(node);
if (node->opcode() == kShiftOpcode) {
BinopMatcher m(node);
if (m.right().HasValue()) {
int32_t value = m.right().Value();
typename BinopMatcher::RightMatcher::ValueType value =
m.right().Value();
if (value >= 0 && value <= 3) {
return value;
}
}
} else if (node->opcode() == IrOpcode::kInt32Mul) {
Int32BinopMatcher m(node);
} else if (node->opcode() == kMulOpcode) {
BinopMatcher m(node);
if (m.right().HasValue()) {
int32_t value = m.right().Value();
typename BinopMatcher::RightMatcher::ValueType value =
m.right().Value();
if (value == 1) {
return 0;
} else if (value == 2) {
......@@ -202,20 +213,20 @@ struct Int32AddMatcher : public Int32BinopMatcher {
}
void PutScaledInputOnLeft() {
scale_exponent_ = GetInputScaleExponent(right().node());
scale_exponent_ = GetInputScaleExponent(this->right().node());
if (scale_exponent_ >= 0) {
int left_scale_exponent = GetInputScaleExponent(left().node());
int left_scale_exponent = GetInputScaleExponent(this->left().node());
if (left_scale_exponent == -1) {
SwapInputs();
this->SwapInputs();
} else {
scale_exponent_ = left_scale_exponent;
}
} else {
scale_exponent_ = GetInputScaleExponent(left().node());
scale_exponent_ = GetInputScaleExponent(this->left().node());
if (scale_exponent_ == -1) {
if (right().opcode() == IrOpcode::kInt32Add &&
left().opcode() != IrOpcode::kInt32Add) {
SwapInputs();
if (this->right().opcode() == kAddOpcode &&
this->left().opcode() != kAddOpcode) {
this->SwapInputs();
}
}
}
......@@ -224,6 +235,12 @@ struct Int32AddMatcher : public Int32BinopMatcher {
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 {
explicit ScaledWithOffsetMatcher(Node* node)
: matches_(false),
......@@ -231,13 +248,12 @@ struct ScaledWithOffsetMatcher {
scale_exponent_(0),
offset_(NULL),
constant_(NULL) {
if (node->opcode() != IrOpcode::kInt32Add) return;
// The Int32AddMatcher canonicalizes the order of constants and scale
// factors that are used as inputs, so instead of enumerating all possible
// patterns by brute force, checking for node clusters using the following
// templates in the following order suffices to find all of the interesting
// cases (S = scaled input, O = offset input, C = constant input):
// The ScaledWithOffsetMatcher canonicalizes the order of constants and
// scale factors that are used as inputs, so instead of enumerating all
// possible patterns by brute force, checking for node clusters using the
// following templates in the following order suffices to find all of the
// interesting cases (S = scaled input, O = offset input, C = constant
// input):
// (S + (O + C))
// (S + (O + O))
// (S + C)
......@@ -248,14 +264,15 @@ struct ScaledWithOffsetMatcher {
// ((O + O) + C)
// (O + C)
// (O + O)
Int32AddMatcher base_matcher(node);
if (node->InputCount() < 2) return;
AddMatcher base_matcher(node);
Node* left = base_matcher.left().node();
Node* right = base_matcher.right().node();
if (base_matcher.HasScaledInput() && left->OwnedBy(node)) {
scaled_ = base_matcher.ScaledInput();
scale_exponent_ = base_matcher.ScaleExponent();
if (right->opcode() == IrOpcode::kInt32Add && right->OwnedBy(node)) {
Int32AddMatcher right_matcher(right);
if (right->opcode() == AddMatcher::kOpcode && right->OwnedBy(node)) {
AddMatcher right_matcher(right);
if (right_matcher.right().HasValue()) {
// (S + (O + C))
offset_ = right_matcher.left().node();
......@@ -272,8 +289,8 @@ struct ScaledWithOffsetMatcher {
offset_ = right;
}
} else {
if (left->opcode() == IrOpcode::kInt32Add && left->OwnedBy(node)) {
Int32AddMatcher left_matcher(left);
if (left->opcode() == AddMatcher::kOpcode && left->OwnedBy(node)) {
AddMatcher left_matcher(left);
Node* left_left = left_matcher.left().node();
Node* left_right = left_matcher.right().node();
if (left_matcher.HasScaledInput() && left_left->OwnedBy(left)) {
......@@ -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;
}
......@@ -340,6 +376,9 @@ struct ScaledWithOffsetMatcher {
Node* constant_;
};
typedef ScaledWithOffsetMatcher<Int32AddMatcher> ScaledWithOffset32Matcher;
typedef ScaledWithOffsetMatcher<Int64AddMatcher> ScaledWithOffset64Matcher;
} // namespace compiler
} // namespace internal
} // namespace v8
......
......@@ -388,9 +388,12 @@ AddressingMode GenerateMemoryOperandInputs(X64OperandGenerator* g, Node* scaled,
mode = kMRn_modes[scale_exponent];
}
} else {
DCHECK(constant != NULL);
inputs[(*input_count)++] = g->UseImmediate(constant);
mode = kMode_MRI;
if (constant == NULL) {
mode = kMode_MR;
} else {
inputs[(*input_count)++] = g->UseImmediate(constant);
mode = kMode_MRI;
}
}
} else {
DCHECK(scaled != NULL);
......@@ -415,7 +418,7 @@ AddressingMode GenerateMemoryOperandInputs(X64OperandGenerator* g, Node* scaled,
void InstructionSelector::VisitInt32Add(Node* node) {
// Try to match the Add to a leal pattern
ScaledWithOffsetMatcher m(node);
ScaledWithOffset32Matcher m(node);
X64OperandGenerator g(this);
if (m.matches() && (m.constant() == NULL || g.CanBeImmediate(m.constant()))) {
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