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

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: Tweaks 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
Index: src/compiler/node-matchers.h
diff --git a/src/compiler/node-matchers.h b/src/compiler/node-matchers.h
index a55e7bf0a22b529ac36304b3458ae426ece9eead..514c53dc505b40b2f19aa0c6302e973fa2c6c0cf 100644
--- a/src/compiler/node-matchers.h
+++ b/src/compiler/node-matchers.h
@@ -116,7 +116,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 +128,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 +155,184 @@ 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), has_scaled_input_(false), scale_factor_(-1) {
+ PutScaledInputOnLeft();
+ if (HasScaledInput()) {
+ Int32BinopMatcher m(left().node());
+ if (m.opcode() == IrOpcode::kWord32Shl) {
+ scale_factor_ = 1 << m.right().Value();
+ } else {
+ DCHECK(m.opcode() == IrOpcode::kInt32Mul);
+ scale_factor_ = m.right().Value();
+ }
+ }
+ }
+
+ bool HasScaledInput() const { return has_scaled_input_; }
+ Node* ScaledInput() const {
+ DCHECK(HasScaledInput());
+ return left().node()->InputAt(0);
+ }
+ int ScaleFactor() const {
+ DCHECK(HasScaledInput());
+ return scale_factor_;
+ }
+
+ private:
+ bool IsScaledInput(Node* node) const {
titzer 2014/11/06 11:47:06 You could also have this method return the scaled
danno 2014/11/06 23:34:07 Done.
+ if (node->opcode() == IrOpcode::kWord32Shl) {
+ Int32BinopMatcher m(node->InputAt(1));
+ if (m.right().HasValue()) {
+ int32_t value = m.right().Value();
+ return (value == 0) || (value == 1) || (value == 2) || (value == 3);
+ }
+ } else if (node->opcode() == IrOpcode::kInt32Mul) {
+ Int32BinopMatcher m(node->InputAt(1));
+ if (m.right().HasValue()) {
+ int32_t value = m.right().Value();
+ return (value == 1) || (value == 2) || (value == 4) || (value == 8);
+ }
+ }
+ return false;
+ }
+
+ void PutScaledInputOnLeft() {
+ if (IsScaledInput(right().node()) && !IsScaledInput(left().node())) {
+ SwapInputs();
+ }
+
+ if (IsScaledInput(left().node())) {
+ has_scaled_input_ = true;
+ } else {
+ if (right().opcode() == IrOpcode::kInt32Add &&
+ left().opcode() != IrOpcode::kInt32Add) {
+ SwapInputs();
+ }
+ }
+ }
+
+ bool has_scaled_input_;
+ int scale_factor_;
+};
+
+struct ScaledWithOffsetMatcher {
+ explicit ScaledWithOffsetMatcher(Node* node)
+ : matches_(false),
+ scaled_(NULL),
+ scale_factor_(1),
+ 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_factor_ = base_matcher.ScaleFactor();
+ 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_factor_ = left_matcher.ScaleFactor();
+ 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_; }
titzer 2014/11/06 11:47:06 Lower case for simple getters.
danno 2014/11/06 23:34:07 Done.
+ Node* Scaled() const { return scaled_; }
+ int ScaleFactor() const { return scale_factor_; }
+ Node* Offset() const { return offset_; }
+ Node* Constant() const { return constant_; }
+
+ private:
+ bool matches_;
+
+ protected:
+ Node* scaled_;
+ int scale_factor_;
+ 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') | src/compiler/x64/instruction-selector-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698