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
3 // found in the LICENSE file.
4 
5 #include "src/compiler/graph-unittest.h"
6 
7 #include <ostream>  // NOLINT(readability/streams)
8 
9 #include "src/compiler/node-properties-inl.h"
10 
11 using testing::_;
12 using testing::MakeMatcher;
13 using testing::MatcherInterface;
14 using testing::MatchResultListener;
15 using testing::StringMatchResultListener;
16 
17 namespace v8 {
18 namespace internal {
19 
20 // TODO(bmeurer): Find a new home for these functions.
21 template <typename T>
operator <<(std::ostream & os,const Unique<T> & value)22 inline std::ostream& operator<<(std::ostream& os, const Unique<T>& value) {
23   return os << *value.handle();
24 }
operator <<(std::ostream & os,const ExternalReference & value)25 inline std::ostream& operator<<(std::ostream& os,
26                                 const ExternalReference& value) {
27   OStringStream ost;
28   compiler::StaticParameterTraits<ExternalReference>::PrintTo(ost, value);
29   return os << ost.c_str();
30 }
31 
32 namespace compiler {
33 
GraphTest(int num_parameters)34 GraphTest::GraphTest(int num_parameters) : common_(zone()), graph_(zone()) {
35   graph()->SetStart(graph()->NewNode(common()->Start(num_parameters)));
36 }
37 
38 
~GraphTest()39 GraphTest::~GraphTest() {}
40 
41 
Parameter(int32_t index)42 Node* GraphTest::Parameter(int32_t index) {
43   return graph()->NewNode(common()->Parameter(index), graph()->start());
44 }
45 
46 
Float32Constant(volatile float value)47 Node* GraphTest::Float32Constant(volatile float value) {
48   return graph()->NewNode(common()->Float32Constant(value));
49 }
50 
51 
Float64Constant(volatile double value)52 Node* GraphTest::Float64Constant(volatile double value) {
53   return graph()->NewNode(common()->Float64Constant(value));
54 }
55 
56 
Int32Constant(int32_t value)57 Node* GraphTest::Int32Constant(int32_t value) {
58   return graph()->NewNode(common()->Int32Constant(value));
59 }
60 
61 
Int64Constant(int64_t value)62 Node* GraphTest::Int64Constant(int64_t value) {
63   return graph()->NewNode(common()->Int64Constant(value));
64 }
65 
66 
NumberConstant(volatile double value)67 Node* GraphTest::NumberConstant(volatile double value) {
68   return graph()->NewNode(common()->NumberConstant(value));
69 }
70 
71 
HeapConstant(const Unique<HeapObject> & value)72 Node* GraphTest::HeapConstant(const Unique<HeapObject>& value) {
73   return graph()->NewNode(common()->HeapConstant(value));
74 }
75 
76 
FalseConstant()77 Node* GraphTest::FalseConstant() {
78   return HeapConstant(
79       Unique<HeapObject>::CreateImmovable(factory()->false_value()));
80 }
81 
82 
TrueConstant()83 Node* GraphTest::TrueConstant() {
84   return HeapConstant(
85       Unique<HeapObject>::CreateImmovable(factory()->true_value()));
86 }
87 
88 
IsFalseConstant()89 Matcher<Node*> GraphTest::IsFalseConstant() {
90   return IsHeapConstant(
91       Unique<HeapObject>::CreateImmovable(factory()->false_value()));
92 }
93 
94 
IsTrueConstant()95 Matcher<Node*> GraphTest::IsTrueConstant() {
96   return IsHeapConstant(
97       Unique<HeapObject>::CreateImmovable(factory()->true_value()));
98 }
99 
100 namespace {
101 
102 template <typename T>
PrintMatchAndExplain(const T & value,const char * value_name,const Matcher<T> & value_matcher,MatchResultListener * listener)103 bool PrintMatchAndExplain(const T& value, const char* value_name,
104                           const Matcher<T>& value_matcher,
105                           MatchResultListener* listener) {
106   StringMatchResultListener value_listener;
107   if (!value_matcher.MatchAndExplain(value, &value_listener)) {
108     *listener << "whose " << value_name << " " << value << " doesn't match";
109     if (value_listener.str() != "") {
110       *listener << ", " << value_listener.str();
111     }
112     return false;
113   }
114   return true;
115 }
116 
117 
118 class NodeMatcher : public MatcherInterface<Node*> {
119  public:
NodeMatcher(IrOpcode::Value opcode)120   explicit NodeMatcher(IrOpcode::Value opcode) : opcode_(opcode) {}
121 
DescribeTo(std::ostream * os) const122   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
123     *os << "is a " << IrOpcode::Mnemonic(opcode_) << " node";
124   }
125 
MatchAndExplain(Node * node,MatchResultListener * listener) const126   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
127       OVERRIDE {
128     if (node == NULL) {
129       *listener << "which is NULL";
130       return false;
131     }
132     if (node->opcode() != opcode_) {
133       *listener << "whose opcode is " << IrOpcode::Mnemonic(node->opcode())
134                 << " but should have been " << IrOpcode::Mnemonic(opcode_);
135       return false;
136     }
137     return true;
138   }
139 
140  private:
141   const IrOpcode::Value opcode_;
142 };
143 
144 
145 class IsBranchMatcher FINAL : public NodeMatcher {
146  public:
IsBranchMatcher(const Matcher<Node * > & value_matcher,const Matcher<Node * > & control_matcher)147   IsBranchMatcher(const Matcher<Node*>& value_matcher,
148                   const Matcher<Node*>& control_matcher)
149       : NodeMatcher(IrOpcode::kBranch),
150         value_matcher_(value_matcher),
151         control_matcher_(control_matcher) {}
152 
DescribeTo(std::ostream * os) const153   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
154     NodeMatcher::DescribeTo(os);
155     *os << " whose value (";
156     value_matcher_.DescribeTo(os);
157     *os << ") and control (";
158     control_matcher_.DescribeTo(os);
159     *os << ")";
160   }
161 
MatchAndExplain(Node * node,MatchResultListener * listener) const162   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
163       OVERRIDE {
164     return (NodeMatcher::MatchAndExplain(node, listener) &&
165             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
166                                  "value", value_matcher_, listener) &&
167             PrintMatchAndExplain(NodeProperties::GetControlInput(node),
168                                  "control", control_matcher_, listener));
169   }
170 
171  private:
172   const Matcher<Node*> value_matcher_;
173   const Matcher<Node*> control_matcher_;
174 };
175 
176 
177 class IsMergeMatcher FINAL : public NodeMatcher {
178  public:
IsMergeMatcher(const Matcher<Node * > & control0_matcher,const Matcher<Node * > & control1_matcher)179   IsMergeMatcher(const Matcher<Node*>& control0_matcher,
180                  const Matcher<Node*>& control1_matcher)
181       : NodeMatcher(IrOpcode::kMerge),
182         control0_matcher_(control0_matcher),
183         control1_matcher_(control1_matcher) {}
184 
DescribeTo(std::ostream * os) const185   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
186     NodeMatcher::DescribeTo(os);
187     *os << " whose control0 (";
188     control0_matcher_.DescribeTo(os);
189     *os << ") and control1 (";
190     control1_matcher_.DescribeTo(os);
191     *os << ")";
192   }
193 
MatchAndExplain(Node * node,MatchResultListener * listener) const194   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
195       OVERRIDE {
196     return (NodeMatcher::MatchAndExplain(node, listener) &&
197             PrintMatchAndExplain(NodeProperties::GetControlInput(node, 0),
198                                  "control0", control0_matcher_, listener) &&
199             PrintMatchAndExplain(NodeProperties::GetControlInput(node, 1),
200                                  "control1", control1_matcher_, listener));
201   }
202 
203  private:
204   const Matcher<Node*> control0_matcher_;
205   const Matcher<Node*> control1_matcher_;
206 };
207 
208 
209 class IsControl1Matcher FINAL : public NodeMatcher {
210  public:
IsControl1Matcher(IrOpcode::Value opcode,const Matcher<Node * > & control_matcher)211   IsControl1Matcher(IrOpcode::Value opcode,
212                     const Matcher<Node*>& control_matcher)
213       : NodeMatcher(opcode), control_matcher_(control_matcher) {}
214 
DescribeTo(std::ostream * os) const215   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
216     NodeMatcher::DescribeTo(os);
217     *os << " whose control (";
218     control_matcher_.DescribeTo(os);
219     *os << ")";
220   }
221 
MatchAndExplain(Node * node,MatchResultListener * listener) const222   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
223       OVERRIDE {
224     return (NodeMatcher::MatchAndExplain(node, listener) &&
225             PrintMatchAndExplain(NodeProperties::GetControlInput(node),
226                                  "control", control_matcher_, listener));
227   }
228 
229  private:
230   const Matcher<Node*> control_matcher_;
231 };
232 
233 
234 class IsFinishMatcher FINAL : public NodeMatcher {
235  public:
IsFinishMatcher(const Matcher<Node * > & value_matcher,const Matcher<Node * > & effect_matcher)236   IsFinishMatcher(const Matcher<Node*>& value_matcher,
237                   const Matcher<Node*>& effect_matcher)
238       : NodeMatcher(IrOpcode::kFinish),
239         value_matcher_(value_matcher),
240         effect_matcher_(effect_matcher) {}
241 
DescribeTo(std::ostream * os) const242   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
243     NodeMatcher::DescribeTo(os);
244     *os << " whose value (";
245     value_matcher_.DescribeTo(os);
246     *os << ") and effect (";
247     effect_matcher_.DescribeTo(os);
248     *os << ")";
249   }
250 
MatchAndExplain(Node * node,MatchResultListener * listener) const251   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
252       OVERRIDE {
253     return (NodeMatcher::MatchAndExplain(node, listener) &&
254             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
255                                  "value", value_matcher_, listener) &&
256             PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
257                                  effect_matcher_, listener));
258   }
259 
260  private:
261   const Matcher<Node*> value_matcher_;
262   const Matcher<Node*> effect_matcher_;
263 };
264 
265 
266 template <typename T>
267 class IsConstantMatcher FINAL : public NodeMatcher {
268  public:
IsConstantMatcher(IrOpcode::Value opcode,const Matcher<T> & value_matcher)269   IsConstantMatcher(IrOpcode::Value opcode, const Matcher<T>& value_matcher)
270       : NodeMatcher(opcode), value_matcher_(value_matcher) {}
271 
DescribeTo(std::ostream * os) const272   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
273     NodeMatcher::DescribeTo(os);
274     *os << " whose value (";
275     value_matcher_.DescribeTo(os);
276     *os << ")";
277   }
278 
MatchAndExplain(Node * node,MatchResultListener * listener) const279   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
280       OVERRIDE {
281     return (NodeMatcher::MatchAndExplain(node, listener) &&
282             PrintMatchAndExplain(OpParameter<T>(node), "value", value_matcher_,
283                                  listener));
284   }
285 
286  private:
287   const Matcher<T> value_matcher_;
288 };
289 
290 
291 class IsPhiMatcher FINAL : public NodeMatcher {
292  public:
IsPhiMatcher(const Matcher<MachineType> & type_matcher,const Matcher<Node * > & value0_matcher,const Matcher<Node * > & value1_matcher,const Matcher<Node * > & control_matcher)293   IsPhiMatcher(const Matcher<MachineType>& type_matcher,
294                const Matcher<Node*>& value0_matcher,
295                const Matcher<Node*>& value1_matcher,
296                const Matcher<Node*>& control_matcher)
297       : NodeMatcher(IrOpcode::kPhi),
298         type_matcher_(type_matcher),
299         value0_matcher_(value0_matcher),
300         value1_matcher_(value1_matcher),
301         control_matcher_(control_matcher) {}
302 
DescribeTo(std::ostream * os) const303   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
304     NodeMatcher::DescribeTo(os);
305     *os << " whose type (";
306     type_matcher_.DescribeTo(os);
307     *os << "), value0 (";
308     value0_matcher_.DescribeTo(os);
309     *os << "), value1 (";
310     value1_matcher_.DescribeTo(os);
311     *os << ") and control (";
312     control_matcher_.DescribeTo(os);
313     *os << ")";
314   }
315 
MatchAndExplain(Node * node,MatchResultListener * listener) const316   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
317       OVERRIDE {
318     return (NodeMatcher::MatchAndExplain(node, listener) &&
319             PrintMatchAndExplain(OpParameter<MachineType>(node), "type",
320                                  type_matcher_, listener) &&
321             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
322                                  "value0", value0_matcher_, listener) &&
323             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
324                                  "value1", value1_matcher_, listener) &&
325             PrintMatchAndExplain(NodeProperties::GetControlInput(node),
326                                  "control", control_matcher_, listener));
327   }
328 
329  private:
330   const Matcher<MachineType> type_matcher_;
331   const Matcher<Node*> value0_matcher_;
332   const Matcher<Node*> value1_matcher_;
333   const Matcher<Node*> control_matcher_;
334 };
335 
336 
337 class IsProjectionMatcher FINAL : public NodeMatcher {
338  public:
IsProjectionMatcher(const Matcher<size_t> & index_matcher,const Matcher<Node * > & base_matcher)339   IsProjectionMatcher(const Matcher<size_t>& index_matcher,
340                       const Matcher<Node*>& base_matcher)
341       : NodeMatcher(IrOpcode::kProjection),
342         index_matcher_(index_matcher),
343         base_matcher_(base_matcher) {}
344 
DescribeTo(std::ostream * os) const345   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
346     NodeMatcher::DescribeTo(os);
347     *os << " whose index (";
348     index_matcher_.DescribeTo(os);
349     *os << ") and base (";
350     base_matcher_.DescribeTo(os);
351     *os << ")";
352   }
353 
MatchAndExplain(Node * node,MatchResultListener * listener) const354   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
355       OVERRIDE {
356     return (NodeMatcher::MatchAndExplain(node, listener) &&
357             PrintMatchAndExplain(OpParameter<size_t>(node), "index",
358                                  index_matcher_, listener) &&
359             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
360                                  base_matcher_, listener));
361   }
362 
363  private:
364   const Matcher<size_t> index_matcher_;
365   const Matcher<Node*> base_matcher_;
366 };
367 
368 
369 class IsCallMatcher FINAL : public NodeMatcher {
370  public:
IsCallMatcher(const Matcher<CallDescriptor * > & descriptor_matcher,const Matcher<Node * > & value0_matcher,const Matcher<Node * > & value1_matcher,const Matcher<Node * > & value2_matcher,const Matcher<Node * > & value3_matcher,const Matcher<Node * > & effect_matcher,const Matcher<Node * > & control_matcher)371   IsCallMatcher(const Matcher<CallDescriptor*>& descriptor_matcher,
372                 const Matcher<Node*>& value0_matcher,
373                 const Matcher<Node*>& value1_matcher,
374                 const Matcher<Node*>& value2_matcher,
375                 const Matcher<Node*>& value3_matcher,
376                 const Matcher<Node*>& effect_matcher,
377                 const Matcher<Node*>& control_matcher)
378       : NodeMatcher(IrOpcode::kCall),
379         descriptor_matcher_(descriptor_matcher),
380         value0_matcher_(value0_matcher),
381         value1_matcher_(value1_matcher),
382         value2_matcher_(value2_matcher),
383         value3_matcher_(value3_matcher),
384         effect_matcher_(effect_matcher),
385         control_matcher_(control_matcher) {}
386 
DescribeTo(std::ostream * os) const387   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
388     NodeMatcher::DescribeTo(os);
389     *os << " whose value0 (";
390     value0_matcher_.DescribeTo(os);
391     *os << ") and value1 (";
392     value1_matcher_.DescribeTo(os);
393     *os << ") and value2 (";
394     value2_matcher_.DescribeTo(os);
395     *os << ") and value3 (";
396     value3_matcher_.DescribeTo(os);
397     *os << ") and effect (";
398     effect_matcher_.DescribeTo(os);
399     *os << ") and control (";
400     control_matcher_.DescribeTo(os);
401     *os << ")";
402   }
403 
MatchAndExplain(Node * node,MatchResultListener * listener) const404   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
405       OVERRIDE {
406     return (NodeMatcher::MatchAndExplain(node, listener) &&
407             PrintMatchAndExplain(OpParameter<CallDescriptor*>(node),
408                                  "descriptor", descriptor_matcher_, listener) &&
409             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
410                                  "value0", value0_matcher_, listener) &&
411             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
412                                  "value1", value1_matcher_, listener) &&
413             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2),
414                                  "value2", value2_matcher_, listener) &&
415             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 3),
416                                  "value3", value3_matcher_, listener) &&
417             PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
418                                  effect_matcher_, listener) &&
419             PrintMatchAndExplain(NodeProperties::GetControlInput(node),
420                                  "control", control_matcher_, listener));
421   }
422 
423  private:
424   const Matcher<CallDescriptor*> descriptor_matcher_;
425   const Matcher<Node*> value0_matcher_;
426   const Matcher<Node*> value1_matcher_;
427   const Matcher<Node*> value2_matcher_;
428   const Matcher<Node*> value3_matcher_;
429   const Matcher<Node*> effect_matcher_;
430   const Matcher<Node*> control_matcher_;
431 };
432 
433 
434 class IsLoadMatcher FINAL : public NodeMatcher {
435  public:
IsLoadMatcher(const Matcher<LoadRepresentation> & rep_matcher,const Matcher<Node * > & base_matcher,const Matcher<Node * > & index_matcher,const Matcher<Node * > & effect_matcher)436   IsLoadMatcher(const Matcher<LoadRepresentation>& rep_matcher,
437                 const Matcher<Node*>& base_matcher,
438                 const Matcher<Node*>& index_matcher,
439                 const Matcher<Node*>& effect_matcher)
440       : NodeMatcher(IrOpcode::kLoad),
441         rep_matcher_(rep_matcher),
442         base_matcher_(base_matcher),
443         index_matcher_(index_matcher),
444         effect_matcher_(effect_matcher) {}
445 
DescribeTo(std::ostream * os) const446   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
447     NodeMatcher::DescribeTo(os);
448     *os << " whose rep (";
449     rep_matcher_.DescribeTo(os);
450     *os << "), base (";
451     base_matcher_.DescribeTo(os);
452     *os << "), index (";
453     index_matcher_.DescribeTo(os);
454     *os << ") and effect (";
455     effect_matcher_.DescribeTo(os);
456     *os << ")";
457   }
458 
MatchAndExplain(Node * node,MatchResultListener * listener) const459   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
460       OVERRIDE {
461     return (NodeMatcher::MatchAndExplain(node, listener) &&
462             PrintMatchAndExplain(OpParameter<LoadRepresentation>(node), "rep",
463                                  rep_matcher_, listener) &&
464             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
465                                  base_matcher_, listener) &&
466             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
467                                  "index", index_matcher_, listener) &&
468             PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
469                                  effect_matcher_, listener));
470   }
471 
472  private:
473   const Matcher<LoadRepresentation> rep_matcher_;
474   const Matcher<Node*> base_matcher_;
475   const Matcher<Node*> index_matcher_;
476   const Matcher<Node*> effect_matcher_;
477 };
478 
479 
480 class IsStoreMatcher FINAL : public NodeMatcher {
481  public:
IsStoreMatcher(const Matcher<MachineType> & type_matcher,const Matcher<WriteBarrierKind> write_barrier_matcher,const Matcher<Node * > & base_matcher,const Matcher<Node * > & index_matcher,const Matcher<Node * > & value_matcher,const Matcher<Node * > & effect_matcher,const Matcher<Node * > & control_matcher)482   IsStoreMatcher(const Matcher<MachineType>& type_matcher,
483                  const Matcher<WriteBarrierKind> write_barrier_matcher,
484                  const Matcher<Node*>& base_matcher,
485                  const Matcher<Node*>& index_matcher,
486                  const Matcher<Node*>& value_matcher,
487                  const Matcher<Node*>& effect_matcher,
488                  const Matcher<Node*>& control_matcher)
489       : NodeMatcher(IrOpcode::kStore),
490         type_matcher_(type_matcher),
491         write_barrier_matcher_(write_barrier_matcher),
492         base_matcher_(base_matcher),
493         index_matcher_(index_matcher),
494         value_matcher_(value_matcher),
495         effect_matcher_(effect_matcher),
496         control_matcher_(control_matcher) {}
497 
DescribeTo(std::ostream * os) const498   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
499     NodeMatcher::DescribeTo(os);
500     *os << " whose type (";
501     type_matcher_.DescribeTo(os);
502     *os << "), write barrier (";
503     write_barrier_matcher_.DescribeTo(os);
504     *os << "), base (";
505     base_matcher_.DescribeTo(os);
506     *os << "), index (";
507     index_matcher_.DescribeTo(os);
508     *os << "), value (";
509     value_matcher_.DescribeTo(os);
510     *os << "), effect (";
511     effect_matcher_.DescribeTo(os);
512     *os << ") and control (";
513     control_matcher_.DescribeTo(os);
514     *os << ")";
515   }
516 
MatchAndExplain(Node * node,MatchResultListener * listener) const517   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
518       OVERRIDE {
519     return (NodeMatcher::MatchAndExplain(node, listener) &&
520             PrintMatchAndExplain(
521                 OpParameter<StoreRepresentation>(node).machine_type(), "type",
522                 type_matcher_, listener) &&
523             PrintMatchAndExplain(
524                 OpParameter<StoreRepresentation>(node).write_barrier_kind(),
525                 "write barrier", write_barrier_matcher_, listener) &&
526             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
527                                  base_matcher_, listener) &&
528             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
529                                  "index", index_matcher_, listener) &&
530             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2),
531                                  "value", value_matcher_, listener) &&
532             PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
533                                  effect_matcher_, listener) &&
534             PrintMatchAndExplain(NodeProperties::GetControlInput(node),
535                                  "control", control_matcher_, listener));
536   }
537 
538  private:
539   const Matcher<MachineType> type_matcher_;
540   const Matcher<WriteBarrierKind> write_barrier_matcher_;
541   const Matcher<Node*> base_matcher_;
542   const Matcher<Node*> index_matcher_;
543   const Matcher<Node*> value_matcher_;
544   const Matcher<Node*> effect_matcher_;
545   const Matcher<Node*> control_matcher_;
546 };
547 
548 
549 class IsBinopMatcher FINAL : public NodeMatcher {
550  public:
IsBinopMatcher(IrOpcode::Value opcode,const Matcher<Node * > & lhs_matcher,const Matcher<Node * > & rhs_matcher)551   IsBinopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& lhs_matcher,
552                  const Matcher<Node*>& rhs_matcher)
553       : NodeMatcher(opcode),
554         lhs_matcher_(lhs_matcher),
555         rhs_matcher_(rhs_matcher) {}
556 
DescribeTo(std::ostream * os) const557   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
558     NodeMatcher::DescribeTo(os);
559     *os << " whose lhs (";
560     lhs_matcher_.DescribeTo(os);
561     *os << ") and rhs (";
562     rhs_matcher_.DescribeTo(os);
563     *os << ")";
564   }
565 
MatchAndExplain(Node * node,MatchResultListener * listener) const566   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
567       OVERRIDE {
568     return (NodeMatcher::MatchAndExplain(node, listener) &&
569             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "lhs",
570                                  lhs_matcher_, listener) &&
571             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), "rhs",
572                                  rhs_matcher_, listener));
573   }
574 
575  private:
576   const Matcher<Node*> lhs_matcher_;
577   const Matcher<Node*> rhs_matcher_;
578 };
579 
580 
581 class IsUnopMatcher FINAL : public NodeMatcher {
582  public:
IsUnopMatcher(IrOpcode::Value opcode,const Matcher<Node * > & input_matcher)583   IsUnopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& input_matcher)
584       : NodeMatcher(opcode), input_matcher_(input_matcher) {}
585 
DescribeTo(std::ostream * os) const586   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
587     NodeMatcher::DescribeTo(os);
588     *os << " whose input (";
589     input_matcher_.DescribeTo(os);
590     *os << ")";
591   }
592 
MatchAndExplain(Node * node,MatchResultListener * listener) const593   virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
594       OVERRIDE {
595     return (NodeMatcher::MatchAndExplain(node, listener) &&
596             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
597                                  "input", input_matcher_, listener));
598   }
599 
600  private:
601   const Matcher<Node*> input_matcher_;
602 };
603 }
604 
605 
IsBranch(const Matcher<Node * > & value_matcher,const Matcher<Node * > & control_matcher)606 Matcher<Node*> IsBranch(const Matcher<Node*>& value_matcher,
607                         const Matcher<Node*>& control_matcher) {
608   return MakeMatcher(new IsBranchMatcher(value_matcher, control_matcher));
609 }
610 
611 
IsMerge(const Matcher<Node * > & control0_matcher,const Matcher<Node * > & control1_matcher)612 Matcher<Node*> IsMerge(const Matcher<Node*>& control0_matcher,
613                        const Matcher<Node*>& control1_matcher) {
614   return MakeMatcher(new IsMergeMatcher(control0_matcher, control1_matcher));
615 }
616 
617 
IsIfTrue(const Matcher<Node * > & control_matcher)618 Matcher<Node*> IsIfTrue(const Matcher<Node*>& control_matcher) {
619   return MakeMatcher(new IsControl1Matcher(IrOpcode::kIfTrue, control_matcher));
620 }
621 
622 
IsIfFalse(const Matcher<Node * > & control_matcher)623 Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher) {
624   return MakeMatcher(
625       new IsControl1Matcher(IrOpcode::kIfFalse, control_matcher));
626 }
627 
628 
IsControlEffect(const Matcher<Node * > & control_matcher)629 Matcher<Node*> IsControlEffect(const Matcher<Node*>& control_matcher) {
630   return MakeMatcher(
631       new IsControl1Matcher(IrOpcode::kControlEffect, control_matcher));
632 }
633 
634 
IsValueEffect(const Matcher<Node * > & value_matcher)635 Matcher<Node*> IsValueEffect(const Matcher<Node*>& value_matcher) {
636   return MakeMatcher(new IsUnopMatcher(IrOpcode::kValueEffect, value_matcher));
637 }
638 
639 
IsFinish(const Matcher<Node * > & value_matcher,const Matcher<Node * > & effect_matcher)640 Matcher<Node*> IsFinish(const Matcher<Node*>& value_matcher,
641                         const Matcher<Node*>& effect_matcher) {
642   return MakeMatcher(new IsFinishMatcher(value_matcher, effect_matcher));
643 }
644 
645 
IsExternalConstant(const Matcher<ExternalReference> & value_matcher)646 Matcher<Node*> IsExternalConstant(
647     const Matcher<ExternalReference>& value_matcher) {
648   return MakeMatcher(new IsConstantMatcher<ExternalReference>(
649       IrOpcode::kExternalConstant, value_matcher));
650 }
651 
652 
IsHeapConstant(const Matcher<Unique<HeapObject>> & value_matcher)653 Matcher<Node*> IsHeapConstant(
654     const Matcher<Unique<HeapObject> >& value_matcher) {
655   return MakeMatcher(new IsConstantMatcher<Unique<HeapObject> >(
656       IrOpcode::kHeapConstant, value_matcher));
657 }
658 
659 
IsInt32Constant(const Matcher<int32_t> & value_matcher)660 Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher) {
661   return MakeMatcher(
662       new IsConstantMatcher<int32_t>(IrOpcode::kInt32Constant, value_matcher));
663 }
664 
665 
IsInt64Constant(const Matcher<int64_t> & value_matcher)666 Matcher<Node*> IsInt64Constant(const Matcher<int64_t>& value_matcher) {
667   return MakeMatcher(
668       new IsConstantMatcher<int64_t>(IrOpcode::kInt64Constant, value_matcher));
669 }
670 
671 
IsFloat32Constant(const Matcher<float> & value_matcher)672 Matcher<Node*> IsFloat32Constant(const Matcher<float>& value_matcher) {
673   return MakeMatcher(
674       new IsConstantMatcher<float>(IrOpcode::kFloat32Constant, value_matcher));
675 }
676 
677 
IsFloat64Constant(const Matcher<double> & value_matcher)678 Matcher<Node*> IsFloat64Constant(const Matcher<double>& value_matcher) {
679   return MakeMatcher(
680       new IsConstantMatcher<double>(IrOpcode::kFloat64Constant, value_matcher));
681 }
682 
683 
IsNumberConstant(const Matcher<double> & value_matcher)684 Matcher<Node*> IsNumberConstant(const Matcher<double>& value_matcher) {
685   return MakeMatcher(
686       new IsConstantMatcher<double>(IrOpcode::kNumberConstant, value_matcher));
687 }
688 
689 
IsPhi(const Matcher<MachineType> & type_matcher,const Matcher<Node * > & value0_matcher,const Matcher<Node * > & value1_matcher,const Matcher<Node * > & merge_matcher)690 Matcher<Node*> IsPhi(const Matcher<MachineType>& type_matcher,
691                      const Matcher<Node*>& value0_matcher,
692                      const Matcher<Node*>& value1_matcher,
693                      const Matcher<Node*>& merge_matcher) {
694   return MakeMatcher(new IsPhiMatcher(type_matcher, value0_matcher,
695                                       value1_matcher, merge_matcher));
696 }
697 
698 
IsProjection(const Matcher<size_t> & index_matcher,const Matcher<Node * > & base_matcher)699 Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
700                             const Matcher<Node*>& base_matcher) {
701   return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher));
702 }
703 
704 
IsCall(const Matcher<CallDescriptor * > & descriptor_matcher,const Matcher<Node * > & value0_matcher,const Matcher<Node * > & value1_matcher,const Matcher<Node * > & value2_matcher,const Matcher<Node * > & value3_matcher,const Matcher<Node * > & effect_matcher,const Matcher<Node * > & control_matcher)705 Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher,
706                       const Matcher<Node*>& value0_matcher,
707                       const Matcher<Node*>& value1_matcher,
708                       const Matcher<Node*>& value2_matcher,
709                       const Matcher<Node*>& value3_matcher,
710                       const Matcher<Node*>& effect_matcher,
711                       const Matcher<Node*>& control_matcher) {
712   return MakeMatcher(new IsCallMatcher(
713       descriptor_matcher, value0_matcher, value1_matcher, value2_matcher,
714       value3_matcher, effect_matcher, control_matcher));
715 }
716 
717 
IsLoad(const Matcher<LoadRepresentation> & rep_matcher,const Matcher<Node * > & base_matcher,const Matcher<Node * > & index_matcher,const Matcher<Node * > & effect_matcher)718 Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
719                       const Matcher<Node*>& base_matcher,
720                       const Matcher<Node*>& index_matcher,
721                       const Matcher<Node*>& effect_matcher) {
722   return MakeMatcher(new IsLoadMatcher(rep_matcher, base_matcher, index_matcher,
723                                        effect_matcher));
724 }
725 
726 
IsStore(const Matcher<MachineType> & type_matcher,const Matcher<WriteBarrierKind> & write_barrier_matcher,const Matcher<Node * > & base_matcher,const Matcher<Node * > & index_matcher,const Matcher<Node * > & value_matcher,const Matcher<Node * > & effect_matcher,const Matcher<Node * > & control_matcher)727 Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher,
728                        const Matcher<WriteBarrierKind>& write_barrier_matcher,
729                        const Matcher<Node*>& base_matcher,
730                        const Matcher<Node*>& index_matcher,
731                        const Matcher<Node*>& value_matcher,
732                        const Matcher<Node*>& effect_matcher,
733                        const Matcher<Node*>& control_matcher) {
734   return MakeMatcher(new IsStoreMatcher(
735       type_matcher, write_barrier_matcher, base_matcher, index_matcher,
736       value_matcher, effect_matcher, control_matcher));
737 }
738 
739 
740 #define IS_BINOP_MATCHER(Name)                                            \
741   Matcher<Node*> Is##Name(const Matcher<Node*>& lhs_matcher,              \
742                           const Matcher<Node*>& rhs_matcher) {            \
743     return MakeMatcher(                                                   \
744         new IsBinopMatcher(IrOpcode::k##Name, lhs_matcher, rhs_matcher)); \
745   }
746 IS_BINOP_MATCHER(NumberLessThan)
747 IS_BINOP_MATCHER(Word32And)
748 IS_BINOP_MATCHER(Word32Sar)
749 IS_BINOP_MATCHER(Word32Shl)
750 IS_BINOP_MATCHER(Word32Ror)
751 IS_BINOP_MATCHER(Word32Equal)
752 IS_BINOP_MATCHER(Word64And)
753 IS_BINOP_MATCHER(Word64Sar)
754 IS_BINOP_MATCHER(Word64Shl)
755 IS_BINOP_MATCHER(Word64Equal)
756 IS_BINOP_MATCHER(Int32AddWithOverflow)
757 IS_BINOP_MATCHER(Int32Mul)
758 IS_BINOP_MATCHER(Uint32LessThanOrEqual)
759 #undef IS_BINOP_MATCHER
760 
761 
762 #define IS_UNOP_MATCHER(Name)                                                \
763   Matcher<Node*> Is##Name(const Matcher<Node*>& input_matcher) {             \
764     return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \
765   }
766 IS_UNOP_MATCHER(ChangeFloat64ToInt32)
767 IS_UNOP_MATCHER(ChangeFloat64ToUint32)
768 IS_UNOP_MATCHER(ChangeInt32ToFloat64)
769 IS_UNOP_MATCHER(ChangeInt32ToInt64)
770 IS_UNOP_MATCHER(ChangeUint32ToFloat64)
771 IS_UNOP_MATCHER(ChangeUint32ToUint64)
772 IS_UNOP_MATCHER(TruncateFloat64ToInt32)
773 IS_UNOP_MATCHER(TruncateInt64ToInt32)
774 IS_UNOP_MATCHER(Float64Sqrt)
775 #undef IS_UNOP_MATCHER
776 
777 }  // namespace compiler
778 }  // namespace internal
779 }  // namespace v8
780