Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_COMPILER_NODE_MATCHERS_H_ | 5 #ifndef V8_COMPILER_NODE_MATCHERS_H_ |
| 6 #define V8_COMPILER_NODE_MATCHERS_H_ | 6 #define V8_COMPILER_NODE_MATCHERS_H_ |
| 7 | 7 |
| 8 #include "src/compiler/node.h" | 8 #include "src/compiler/node.h" |
| 9 #include "src/compiler/operator.h" | 9 #include "src/compiler/operator.h" |
| 10 #include "src/unique.h" | 10 #include "src/unique.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 : public ValueMatcher<Unique<T>, IrOpcode::kHeapConstant> { | 109 : public ValueMatcher<Unique<T>, IrOpcode::kHeapConstant> { |
| 110 explicit HeapObjectMatcher(Node* node) | 110 explicit HeapObjectMatcher(Node* node) |
| 111 : ValueMatcher<Unique<T>, IrOpcode::kHeapConstant>(node) {} | 111 : ValueMatcher<Unique<T>, IrOpcode::kHeapConstant>(node) {} |
| 112 }; | 112 }; |
| 113 | 113 |
| 114 | 114 |
| 115 // For shorter pattern matching code, this struct matches both the left and | 115 // For shorter pattern matching code, this struct matches both the left and |
| 116 // right hand sides of a binary operation and can put constants on the right | 116 // right hand sides of a binary operation and can put constants on the right |
| 117 // if they appear on the left hand side of a commutative operation. | 117 // if they appear on the left hand side of a commutative operation. |
| 118 template <typename Left, typename Right> | 118 template <typename Left, typename Right> |
| 119 struct BinopMatcher FINAL : public NodeMatcher { | 119 struct BinopMatcher : public NodeMatcher { |
| 120 explicit BinopMatcher(Node* node) | 120 explicit BinopMatcher(Node* node) |
| 121 : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { | 121 : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { |
| 122 if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); | 122 if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); |
| 123 } | 123 } |
| 124 | 124 |
| 125 const Left& left() const { return left_; } | 125 const Left& left() const { return left_; } |
| 126 const Right& right() const { return right_; } | 126 const Right& right() const { return right_; } |
| 127 | 127 |
| 128 bool IsFoldable() const { return left().HasValue() && right().HasValue(); } | 128 bool IsFoldable() const { return left().HasValue() && right().HasValue(); } |
| 129 bool LeftEqualsRight() const { return left().node() == right().node(); } | 129 bool LeftEqualsRight() const { return left().node() == right().node(); } |
| 130 | 130 |
| 131 protected: | |
| 132 void SwapInputs() { | |
| 133 std::swap(left_, right_); | |
| 134 node()->ReplaceInput(0, left().node()); | |
| 135 node()->ReplaceInput(1, right().node()); | |
| 136 } | |
| 137 | |
| 131 private: | 138 private: |
| 132 void PutConstantOnRight() { | 139 void PutConstantOnRight() { |
| 133 if (left().HasValue() && !right().HasValue()) { | 140 if (left().HasValue() && !right().HasValue()) { |
| 134 std::swap(left_, right_); | 141 SwapInputs(); |
| 135 node()->ReplaceInput(0, left().node()); | |
| 136 node()->ReplaceInput(1, right().node()); | |
| 137 } | 142 } |
| 138 } | 143 } |
| 139 | 144 |
| 140 Left left_; | 145 Left left_; |
| 141 Right right_; | 146 Right right_; |
| 142 }; | 147 }; |
| 143 | 148 |
| 144 typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher; | 149 typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher; |
| 145 typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher; | 150 typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher; |
| 146 typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher; | 151 typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher; |
| 147 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher; | 152 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher; |
| 148 typedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher; | 153 typedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher; |
| 149 typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; | 154 typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; |
| 150 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; | 155 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; |
| 151 typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; | 156 typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; |
| 152 | 157 |
| 158 struct Int32AddMatcher : public Int32BinopMatcher { | |
| 159 explicit Int32AddMatcher(Node* node) | |
| 160 : Int32BinopMatcher(node), has_scaled_input_(false), scale_factor_(-1) { | |
| 161 PutScaledInputOnLeft(); | |
| 162 if (HasScaledInput()) { | |
| 163 Int32BinopMatcher m(left().node()); | |
| 164 if (m.opcode() == IrOpcode::kWord32Shl) { | |
| 165 scale_factor_ = 1 << m.right().Value(); | |
| 166 } else { | |
| 167 DCHECK(m.opcode() == IrOpcode::kInt32Mul); | |
| 168 scale_factor_ = m.right().Value(); | |
| 169 } | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 bool HasScaledInput() const { return has_scaled_input_; } | |
| 174 Node* ScaledInput() const { | |
| 175 DCHECK(HasScaledInput()); | |
| 176 return left().node()->InputAt(0); | |
| 177 } | |
| 178 int ScaleFactor() const { | |
| 179 DCHECK(HasScaledInput()); | |
| 180 return scale_factor_; | |
| 181 } | |
| 182 | |
| 183 private: | |
| 184 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.
| |
| 185 if (node->opcode() == IrOpcode::kWord32Shl) { | |
| 186 Int32BinopMatcher m(node->InputAt(1)); | |
| 187 if (m.right().HasValue()) { | |
| 188 int32_t value = m.right().Value(); | |
| 189 return (value == 0) || (value == 1) || (value == 2) || (value == 3); | |
| 190 } | |
| 191 } else if (node->opcode() == IrOpcode::kInt32Mul) { | |
| 192 Int32BinopMatcher m(node->InputAt(1)); | |
| 193 if (m.right().HasValue()) { | |
| 194 int32_t value = m.right().Value(); | |
| 195 return (value == 1) || (value == 2) || (value == 4) || (value == 8); | |
| 196 } | |
| 197 } | |
| 198 return false; | |
| 199 } | |
| 200 | |
| 201 void PutScaledInputOnLeft() { | |
| 202 if (IsScaledInput(right().node()) && !IsScaledInput(left().node())) { | |
| 203 SwapInputs(); | |
| 204 } | |
| 205 | |
| 206 if (IsScaledInput(left().node())) { | |
| 207 has_scaled_input_ = true; | |
| 208 } else { | |
| 209 if (right().opcode() == IrOpcode::kInt32Add && | |
| 210 left().opcode() != IrOpcode::kInt32Add) { | |
| 211 SwapInputs(); | |
| 212 } | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 bool has_scaled_input_; | |
| 217 int scale_factor_; | |
| 218 }; | |
| 219 | |
| 220 struct ScaledWithOffsetMatcher { | |
| 221 explicit ScaledWithOffsetMatcher(Node* node) | |
| 222 : matches_(false), | |
| 223 scaled_(NULL), | |
| 224 scale_factor_(1), | |
| 225 offset_(NULL), | |
| 226 constant_(NULL) { | |
| 227 if (node->opcode() != IrOpcode::kInt32Add) return; | |
| 228 | |
| 229 // The Int32AddMatcher canonicalizes the order of constants and scale | |
| 230 // factors that are used as inputs, so instead of enumerating all possible | |
| 231 // patterns by brute force, checking for node clusters using the following | |
| 232 // templates in the following order suffices to find all of the interesting | |
| 233 // cases (S = scaled input, O = offset input, C = constant input): | |
| 234 // (S + (O + C)) | |
| 235 // (S + (O + O)) | |
| 236 // (S + C) | |
| 237 // (S + O) | |
| 238 // ((S + C) + O) | |
| 239 // ((S + O) + C) | |
| 240 // ((O + C) + O) | |
| 241 // ((O + O) + C) | |
| 242 // (O + C) | |
| 243 // (O + O) | |
| 244 Int32AddMatcher base_matcher(node); | |
| 245 Node* left = base_matcher.left().node(); | |
| 246 Node* right = base_matcher.right().node(); | |
| 247 if (base_matcher.HasScaledInput() && left->OwnedBy(node)) { | |
| 248 scaled_ = base_matcher.ScaledInput(); | |
| 249 scale_factor_ = base_matcher.ScaleFactor(); | |
| 250 if (right->opcode() == IrOpcode::kInt32Add && right->OwnedBy(node)) { | |
| 251 Int32AddMatcher right_matcher(right); | |
| 252 if (right_matcher.right().HasValue()) { | |
| 253 // (S + (O + C)) | |
| 254 offset_ = right_matcher.left().node(); | |
| 255 constant_ = right_matcher.right().node(); | |
| 256 } else { | |
| 257 // (S + (O + O)) | |
| 258 offset_ = right; | |
| 259 } | |
| 260 } else if (base_matcher.right().HasValue()) { | |
| 261 // (S + C) | |
| 262 constant_ = right; | |
| 263 } else { | |
| 264 // (S + O) | |
| 265 offset_ = right; | |
| 266 } | |
| 267 } else { | |
| 268 if (left->opcode() == IrOpcode::kInt32Add && left->OwnedBy(node)) { | |
| 269 Int32AddMatcher left_matcher(left); | |
| 270 Node* left_left = left_matcher.left().node(); | |
| 271 Node* left_right = left_matcher.right().node(); | |
| 272 if (left_matcher.HasScaledInput() && left_left->OwnedBy(left)) { | |
| 273 scaled_ = left_matcher.ScaledInput(); | |
| 274 scale_factor_ = left_matcher.ScaleFactor(); | |
| 275 if (left_matcher.right().HasValue()) { | |
| 276 // ((S + C) + O) | |
| 277 constant_ = left_right; | |
| 278 offset_ = right; | |
| 279 } else if (base_matcher.right().HasValue()) { | |
| 280 // ((S + O) + C) | |
| 281 offset_ = left_right; | |
| 282 constant_ = right; | |
| 283 } else { | |
| 284 // (O + O) | |
| 285 scaled_ = left; | |
| 286 offset_ = right; | |
| 287 } | |
| 288 } else { | |
| 289 if (left_matcher.right().HasValue()) { | |
| 290 // ((O + C) + O) | |
| 291 scaled_ = left_left; | |
| 292 constant_ = left_right; | |
| 293 offset_ = right; | |
| 294 } else if (base_matcher.right().HasValue()) { | |
| 295 // ((O + O) + C) | |
| 296 scaled_ = left_left; | |
| 297 offset_ = left_right; | |
| 298 constant_ = right; | |
| 299 } else { | |
| 300 // (O + O) | |
| 301 scaled_ = left; | |
| 302 offset_ = right; | |
| 303 } | |
| 304 } | |
| 305 } else { | |
| 306 if (base_matcher.right().HasValue()) { | |
| 307 // (O + C) | |
| 308 offset_ = left; | |
| 309 constant_ = right; | |
| 310 } else { | |
| 311 // (O + O) | |
| 312 offset_ = left; | |
| 313 scaled_ = right; | |
| 314 } | |
| 315 } | |
| 316 } | |
| 317 matches_ = true; | |
| 318 } | |
| 319 | |
| 320 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.
| |
| 321 Node* Scaled() const { return scaled_; } | |
| 322 int ScaleFactor() const { return scale_factor_; } | |
| 323 Node* Offset() const { return offset_; } | |
| 324 Node* Constant() const { return constant_; } | |
| 325 | |
| 326 private: | |
| 327 bool matches_; | |
| 328 | |
| 329 protected: | |
| 330 Node* scaled_; | |
| 331 int scale_factor_; | |
| 332 Node* offset_; | |
| 333 Node* constant_; | |
| 334 }; | |
| 335 | |
| 153 } // namespace compiler | 336 } // namespace compiler |
| 154 } // namespace internal | 337 } // namespace internal |
| 155 } // namespace v8 | 338 } // namespace v8 |
| 156 | 339 |
| 157 #endif // V8_COMPILER_NODE_MATCHERS_H_ | 340 #endif // V8_COMPILER_NODE_MATCHERS_H_ |
| OLD | NEW |