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

Unified Diff: src/compiler/node-matchers.h

Issue 704713003: [turbofan] Optimize add operations to use 'leal' instruction on x64 (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Final version Created 6 years, 1 month 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 | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/node-matchers.h
diff --git a/src/compiler/node-matchers.h b/src/compiler/node-matchers.h
index a55e7bf0a22b529ac36304b3458ae426ece9eead..b1147a7369f9801a75e24f22a2442347fbbfdf70 100644
--- a/src/compiler/node-matchers.h
+++ b/src/compiler/node-matchers.h
@@ -5,6 +5,8 @@
#ifndef V8_COMPILER_NODE_MATCHERS_H_
#define V8_COMPILER_NODE_MATCHERS_H_
+#include "src/compiler/generic-node.h"
+#include "src/compiler/generic-node-inl.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/unique.h"
@@ -116,7 +118,7 @@ struct HeapObjectMatcher FINAL
// right hand sides of a binary operation and can put constants on the right
// if they appear on the left hand side of a commutative operation.
template <typename Left, typename Right>
-struct BinopMatcher FINAL : public NodeMatcher {
+struct BinopMatcher : public NodeMatcher {
explicit BinopMatcher(Node* node)
: NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) {
if (HasProperty(Operator::kCommutative)) PutConstantOnRight();
@@ -128,12 +130,17 @@ struct BinopMatcher FINAL : public NodeMatcher {
bool IsFoldable() const { return left().HasValue() && right().HasValue(); }
bool LeftEqualsRight() const { return left().node() == right().node(); }
+ protected:
+ void SwapInputs() {
+ std::swap(left_, right_);
+ node()->ReplaceInput(0, left().node());
+ node()->ReplaceInput(1, right().node());
+ }
+
private:
void PutConstantOnRight() {
if (left().HasValue() && !right().HasValue()) {
- std::swap(left_, right_);
- node()->ReplaceInput(0, left().node());
- node()->ReplaceInput(1, right().node());
+ SwapInputs();
}
}
@@ -150,6 +157,189 @@ 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();
+ }
+
+ bool HasScaledInput() const { return scale_exponent_ != -1; }
+ Node* ScaledInput() const {
+ DCHECK(HasScaledInput());
+ return left().node()->InputAt(0);
+ }
+ int ScaleExponent() const {
+ DCHECK(HasScaledInput());
+ return scale_exponent_;
+ }
+
+ private:
+ int GetInputScaleExponent(Node* node) const {
+ if (node->opcode() == IrOpcode::kWord32Shl) {
+ Int32BinopMatcher m(node);
+ if (m.right().HasValue()) {
+ int32_t value = m.right().Value();
+ if (value >= 0 && value <= 3) {
+ return value;
+ }
+ }
+ } else if (node->opcode() == IrOpcode::kInt32Mul) {
+ Int32BinopMatcher m(node);
+ if (m.right().HasValue()) {
+ int32_t value = m.right().Value();
+ if (value == 1) {
+ return 0;
+ } else if (value == 2) {
+ return 1;
+ } else if (value == 4) {
+ return 2;
+ } else if (value == 8) {
+ return 3;
+ }
+ }
+ }
+ return -1;
+ }
+
+ void PutScaledInputOnLeft() {
+ scale_exponent_ = GetInputScaleExponent(right().node());
+ if (scale_exponent_ >= 0) {
+ int left_scale_exponent = GetInputScaleExponent(left().node());
+ if (left_scale_exponent == -1) {
+ SwapInputs();
+ } else {
+ scale_exponent_ = left_scale_exponent;
+ }
+ } else {
+ scale_exponent_ = GetInputScaleExponent(left().node());
+ if (scale_exponent_ == -1) {
+ if (right().opcode() == IrOpcode::kInt32Add &&
+ left().opcode() != IrOpcode::kInt32Add) {
+ SwapInputs();
+ }
+ }
+ }
+ }
+
+ int scale_exponent_;
+};
+
+struct ScaledWithOffsetMatcher {
+ explicit ScaledWithOffsetMatcher(Node* node)
+ : matches_(false),
+ scaled_(NULL),
+ 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):
+ // (S + (O + C))
+ // (S + (O + O))
+ // (S + C)
+ // (S + O)
+ // ((S + C) + O)
+ // ((S + O) + C)
+ // ((O + C) + O)
+ // ((O + O) + C)
+ // (O + C)
+ // (O + O)
+ Int32AddMatcher 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_matcher.right().HasValue()) {
+ // (S + (O + C))
+ offset_ = right_matcher.left().node();
+ constant_ = right_matcher.right().node();
+ } else {
+ // (S + (O + O))
+ offset_ = right;
+ }
+ } else if (base_matcher.right().HasValue()) {
+ // (S + C)
+ constant_ = right;
+ } else {
+ // (S + O)
+ offset_ = right;
+ }
+ } else {
+ if (left->opcode() == IrOpcode::kInt32Add && left->OwnedBy(node)) {
+ Int32AddMatcher 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)) {
+ scaled_ = left_matcher.ScaledInput();
+ scale_exponent_ = left_matcher.ScaleExponent();
+ if (left_matcher.right().HasValue()) {
+ // ((S + C) + O)
+ constant_ = left_right;
+ offset_ = right;
+ } else if (base_matcher.right().HasValue()) {
+ // ((S + O) + C)
+ offset_ = left_right;
+ constant_ = right;
+ } else {
+ // (O + O)
+ scaled_ = left;
+ offset_ = right;
+ }
+ } else {
+ if (left_matcher.right().HasValue()) {
+ // ((O + C) + O)
+ scaled_ = left_left;
+ constant_ = left_right;
+ offset_ = right;
+ } else if (base_matcher.right().HasValue()) {
+ // ((O + O) + C)
+ scaled_ = left_left;
+ offset_ = left_right;
+ constant_ = right;
+ } else {
+ // (O + O)
+ scaled_ = left;
+ offset_ = right;
+ }
+ }
+ } else {
+ if (base_matcher.right().HasValue()) {
+ // (O + C)
+ offset_ = left;
+ constant_ = right;
+ } else {
+ // (O + O)
+ offset_ = left;
+ scaled_ = right;
+ }
+ }
+ }
+ matches_ = true;
+ }
+
+ bool matches() const { return matches_; }
+ Node* scaled() const { return scaled_; }
+ int scale_exponent() const { return scale_exponent_; }
+ Node* offset() const { return offset_; }
+ Node* constant() const { return constant_; }
+
+ private:
+ bool matches_;
+
+ protected:
+ Node* scaled_;
+ int scale_exponent_;
+ Node* offset_;
+ Node* constant_;
+};
+
} // namespace compiler
} // namespace internal
} // namespace v8
« no previous file with comments | « no previous file | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698