Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 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/access-builder.h" | |
| 6 #include "src/compiler/graph.h" | |
| 7 #include "src/compiler/graph-visualizer.h" | |
| 8 #include "src/compiler/js-graph.h" | |
| 9 #include "src/compiler/js-operator.h" | |
|
Benedikt Meurer
2015/01/16 17:55:36
This include seems unnecessary.
titzer
2015/01/19 09:47:12
Done.
| |
| 10 #include "src/compiler/js-typed-lowering.h" | |
|
Benedikt Meurer
2015/01/16 17:55:36
This include seems unnecessary.
titzer
2015/01/19 09:47:12
Done.
| |
| 11 #include "src/compiler/loop-peeling.h" | |
| 12 #include "src/compiler/machine-operator.h" | |
| 13 #include "src/compiler/node.h" | |
| 14 #include "src/compiler/node-properties-inl.h" | |
| 15 #include "test/unittests/compiler/compiler-test-utils.h" | |
| 16 #include "test/unittests/compiler/graph-unittest.h" | |
| 17 #include "test/unittests/compiler/node-test-utils.h" | |
| 18 #include "testing/gmock-support.h" | |
| 19 | |
| 20 using testing::AllOf; | |
| 21 using testing::BitEq; | |
| 22 using testing::Capture; | |
| 23 using testing::CaptureEq; | |
| 24 | |
| 25 namespace v8 { | |
| 26 namespace internal { | |
| 27 namespace compiler { | |
| 28 | |
| 29 struct While { | |
| 30 Node* loop; | |
| 31 Node* branch; | |
| 32 Node* if_true; | |
| 33 Node* exit; | |
| 34 }; | |
| 35 | |
| 36 | |
| 37 // A helper for building branches. | |
| 38 struct Branch { | |
| 39 Node* branch; | |
| 40 Node* if_true; | |
| 41 Node* if_false; | |
| 42 }; | |
| 43 | |
| 44 | |
| 45 // A helper for building counters attached to loops. | |
| 46 struct Counter { | |
| 47 Node* base; | |
| 48 Node* inc; | |
| 49 Node* phi; | |
| 50 Node* add; | |
| 51 }; | |
| 52 | |
| 53 | |
| 54 class LoopPeelingTest : public GraphTest { | |
| 55 public: | |
| 56 LoopPeelingTest() : GraphTest(1), machine_(zone()) {} | |
| 57 ~LoopPeelingTest() OVERRIDE {} | |
| 58 | |
| 59 protected: | |
| 60 MachineOperatorBuilder machine_; | |
| 61 | |
| 62 MachineOperatorBuilder* machine() { return &machine_; } | |
| 63 | |
| 64 LoopTree* GetLoopTree() { | |
| 65 if (FLAG_trace_turbo_graph) { | |
| 66 OFStream os(stdout); | |
| 67 os << AsRPO(*graph()); | |
| 68 } | |
| 69 Zone zone(isolate()); | |
| 70 return LoopFinder::BuildLoopTree(graph(), &zone); | |
| 71 } | |
| 72 | |
| 73 | |
| 74 PeeledIteration* PeelOne() { | |
| 75 LoopTree* loop_tree = GetLoopTree(); | |
| 76 return Peel(loop_tree, loop_tree->outer_loops()[0]); | |
| 77 } | |
| 78 | |
| 79 PeeledIteration* Peel(LoopTree* loop_tree, LoopTree::Loop* loop) { | |
| 80 PeeledIteration* peeled = | |
| 81 LoopPeeler::Peel(graph(), common(), loop_tree, loop, zone()); | |
| 82 if (FLAG_trace_turbo_graph) { | |
| 83 OFStream os(stdout); | |
| 84 os << AsRPO(*graph()); | |
| 85 } | |
| 86 return peeled; | |
| 87 } | |
| 88 | |
| 89 Node* InsertReturn(Node* val, Node* effect, Node* control) { | |
| 90 Node* r = graph()->NewNode(common()->Return(), val, effect, control); | |
| 91 graph()->SetEnd(r); | |
| 92 return r; | |
| 93 } | |
| 94 | |
| 95 Node* ExpectPeeled(Node* node, PeeledIteration* iter) { | |
| 96 Node* p = iter->map(node); | |
| 97 EXPECT_NE(node, p); | |
| 98 return p; | |
| 99 } | |
| 100 | |
| 101 void ExpectNotPeeled(Node* node, PeeledIteration* iter) { | |
| 102 EXPECT_EQ(node, iter->map(node)); | |
| 103 } | |
| 104 | |
| 105 While NewWhile(Node* cond, Node* control = nullptr) { | |
| 106 if (control == nullptr) control = start(); | |
| 107 Node* loop = graph()->NewNode(common()->Loop(2), control, control); | |
| 108 Node* branch = graph()->NewNode(common()->Branch(), cond, loop); | |
| 109 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 110 Node* exit = graph()->NewNode(common()->IfFalse(), branch); | |
| 111 loop->ReplaceInput(1, if_true); | |
| 112 return {loop, branch, if_true, exit}; | |
| 113 } | |
| 114 | |
| 115 void Chain(While* a, Node* control) { a->loop->ReplaceInput(0, control); } | |
| 116 void Nest(While* a, While* b) { | |
| 117 b->loop->ReplaceInput(1, a->exit); | |
| 118 a->loop->ReplaceInput(0, b->if_true); | |
| 119 } | |
| 120 Node* NewPhi(While* w, Node* a, Node* b) { | |
| 121 return graph()->NewNode(common()->Phi(kMachAnyTagged, 2), a, b, w->loop); | |
| 122 } | |
| 123 | |
| 124 Branch NewBranch(Node* cond, Node* control = nullptr) { | |
| 125 if (control == nullptr) control = start(); | |
| 126 Node* branch = graph()->NewNode(common()->Branch(), cond, control); | |
| 127 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 128 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 129 return {branch, if_true, if_false}; | |
| 130 } | |
| 131 | |
| 132 Counter NewCounter(While* w, int32_t b, int32_t k) { | |
| 133 Node* base = Int32Constant(b); | |
| 134 Node* inc = Int32Constant(k); | |
| 135 Node* phi = | |
| 136 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), base, base, w->loop); | |
| 137 Node* add = graph()->NewNode(machine()->Int32Add(), phi, inc); | |
| 138 phi->ReplaceInput(1, add); | |
| 139 return {base, inc, phi, add}; | |
| 140 } | |
| 141 }; | |
| 142 | |
| 143 | |
| 144 TEST_F(LoopPeelingTest, SimpleLoop) { | |
| 145 Node* p0 = Parameter(0); | |
| 146 While w = NewWhile(p0); | |
| 147 Node* r = InsertReturn(p0, start(), w.exit); | |
| 148 | |
| 149 PeeledIteration* peeled = PeelOne(); | |
| 150 | |
| 151 Node* br1 = ExpectPeeled(w.branch, peeled); | |
| 152 Node* if_true1 = ExpectPeeled(w.if_true, peeled); | |
| 153 Node* if_false1 = ExpectPeeled(w.exit, peeled); | |
| 154 | |
| 155 EXPECT_THAT(br1, IsBranch(p0, start())); | |
| 156 EXPECT_THAT(if_true1, IsIfTrue(br1)); | |
| 157 EXPECT_THAT(if_false1, IsIfFalse(br1)); | |
| 158 | |
| 159 EXPECT_THAT(w.loop, IsLoop(if_true1, w.if_true)); | |
| 160 EXPECT_THAT(r, IsReturn(p0, start(), IsMerge(w.exit, if_false1))); | |
| 161 } | |
| 162 | |
| 163 | |
| 164 TEST_F(LoopPeelingTest, SimpleLoopWithCounter) { | |
| 165 Node* p0 = Parameter(0); | |
| 166 While w = NewWhile(p0); | |
| 167 Counter c = NewCounter(&w, 0, 1); | |
| 168 Node* r = InsertReturn(c.phi, start(), w.exit); | |
| 169 | |
| 170 PeeledIteration* peeled = PeelOne(); | |
| 171 | |
| 172 Node* br1 = ExpectPeeled(w.branch, peeled); | |
| 173 Node* if_true1 = ExpectPeeled(w.if_true, peeled); | |
| 174 Node* if_false1 = ExpectPeeled(w.exit, peeled); | |
| 175 | |
| 176 EXPECT_THAT(br1, IsBranch(p0, start())); | |
| 177 EXPECT_THAT(if_true1, IsIfTrue(br1)); | |
| 178 EXPECT_THAT(if_false1, IsIfFalse(br1)); | |
| 179 EXPECT_THAT(w.loop, IsLoop(if_true1, w.if_true)); | |
| 180 | |
| 181 EXPECT_THAT(peeled->map(c.add), IsInt32Add(c.base, c.inc)); | |
| 182 | |
| 183 Capture<Node*> merge; | |
| 184 EXPECT_THAT( | |
| 185 r, IsReturn(IsPhi(kMachAnyTagged, c.phi, c.base, | |
| 186 AllOf(CaptureEq(&merge), IsMerge(w.exit, if_false1))), | |
| 187 start(), CaptureEq(&merge))); | |
| 188 } | |
| 189 | |
| 190 | |
| 191 TEST_F(LoopPeelingTest, SimpleNestedLoopWithCounter_peel_outer) { | |
| 192 Node* p0 = Parameter(0); | |
| 193 While outer = NewWhile(p0); | |
| 194 While inner = NewWhile(p0); | |
| 195 Nest(&inner, &outer); | |
| 196 | |
| 197 Counter c = NewCounter(&outer, 0, 1); | |
| 198 Node* r = InsertReturn(c.phi, start(), outer.exit); | |
| 199 | |
| 200 PeeledIteration* peeled = PeelOne(); | |
| 201 | |
| 202 Node* bro = ExpectPeeled(outer.branch, peeled); | |
| 203 Node* if_trueo = ExpectPeeled(outer.if_true, peeled); | |
| 204 Node* if_falseo = ExpectPeeled(outer.exit, peeled); | |
| 205 | |
| 206 EXPECT_THAT(bro, IsBranch(p0, start())); | |
| 207 EXPECT_THAT(if_trueo, IsIfTrue(bro)); | |
| 208 EXPECT_THAT(if_falseo, IsIfFalse(bro)); | |
| 209 | |
| 210 Node* bri = ExpectPeeled(inner.branch, peeled); | |
| 211 Node* if_truei = ExpectPeeled(inner.if_true, peeled); | |
| 212 Node* if_falsei = ExpectPeeled(inner.exit, peeled); | |
| 213 | |
| 214 EXPECT_THAT(bri, IsBranch(p0, ExpectPeeled(inner.loop, peeled))); | |
| 215 EXPECT_THAT(if_truei, IsIfTrue(bri)); | |
| 216 EXPECT_THAT(if_falsei, IsIfFalse(bri)); | |
| 217 | |
| 218 EXPECT_THAT(outer.loop, IsLoop(if_falsei, inner.exit)); | |
| 219 EXPECT_THAT(peeled->map(c.add), IsInt32Add(c.base, c.inc)); | |
| 220 | |
| 221 Capture<Node*> merge; | |
| 222 EXPECT_THAT( | |
| 223 r, | |
| 224 IsReturn(IsPhi(kMachAnyTagged, c.phi, c.base, | |
| 225 AllOf(CaptureEq(&merge), IsMerge(outer.exit, if_falseo))), | |
| 226 start(), CaptureEq(&merge))); | |
| 227 } | |
| 228 | |
| 229 | |
| 230 TEST_F(LoopPeelingTest, SimpleNestedLoopWithCounter_peel_inner) { | |
| 231 Node* p0 = Parameter(0); | |
| 232 While outer = NewWhile(p0); | |
| 233 While inner = NewWhile(p0); | |
| 234 Nest(&inner, &outer); | |
| 235 | |
| 236 Counter c = NewCounter(&outer, 0, 1); | |
| 237 Node* r = InsertReturn(c.phi, start(), outer.exit); | |
| 238 | |
| 239 LoopTree* loop_tree = GetLoopTree(); | |
| 240 LoopTree::Loop* loop = loop_tree->ContainingLoop(inner.loop); | |
| 241 EXPECT_NE(nullptr, loop); | |
| 242 EXPECT_EQ(1, loop->depth()); | |
| 243 | |
| 244 PeeledIteration* peeled = Peel(loop_tree, loop); | |
| 245 | |
| 246 ExpectNotPeeled(outer.loop, peeled); | |
| 247 ExpectNotPeeled(outer.branch, peeled); | |
| 248 ExpectNotPeeled(outer.if_true, peeled); | |
| 249 ExpectNotPeeled(outer.exit, peeled); | |
| 250 | |
| 251 Node* bri = ExpectPeeled(inner.branch, peeled); | |
| 252 Node* if_truei = ExpectPeeled(inner.if_true, peeled); | |
| 253 Node* if_falsei = ExpectPeeled(inner.exit, peeled); | |
| 254 | |
| 255 EXPECT_THAT(bri, IsBranch(p0, ExpectPeeled(inner.loop, peeled))); | |
| 256 EXPECT_THAT(if_truei, IsIfTrue(bri)); | |
| 257 EXPECT_THAT(if_falsei, IsIfFalse(bri)); | |
| 258 | |
| 259 EXPECT_THAT(outer.loop, IsLoop(start(), IsMerge(inner.exit, if_falsei))); | |
| 260 ExpectNotPeeled(c.add, peeled); | |
| 261 | |
| 262 EXPECT_THAT(r, IsReturn(c.phi, start(), outer.exit)); | |
| 263 } | |
| 264 | |
| 265 | |
| 266 TEST_F(LoopPeelingTest, SimpleInnerCounter_peel_inner) { | |
| 267 Node* p0 = Parameter(0); | |
| 268 While outer = NewWhile(p0); | |
| 269 While inner = NewWhile(p0); | |
| 270 Nest(&inner, &outer); | |
| 271 Counter c = NewCounter(&inner, 0, 1); | |
| 272 Node* phi = NewPhi(&outer, Int32Constant(11), c.phi); | |
| 273 | |
| 274 Node* r = InsertReturn(phi, start(), outer.exit); | |
| 275 | |
| 276 LoopTree* loop_tree = GetLoopTree(); | |
| 277 LoopTree::Loop* loop = loop_tree->ContainingLoop(inner.loop); | |
| 278 EXPECT_NE(nullptr, loop); | |
| 279 EXPECT_EQ(1, loop->depth()); | |
| 280 | |
| 281 PeeledIteration* peeled = Peel(loop_tree, loop); | |
| 282 | |
| 283 ExpectNotPeeled(outer.loop, peeled); | |
| 284 ExpectNotPeeled(outer.branch, peeled); | |
| 285 ExpectNotPeeled(outer.if_true, peeled); | |
| 286 ExpectNotPeeled(outer.exit, peeled); | |
| 287 | |
| 288 Node* bri = ExpectPeeled(inner.branch, peeled); | |
| 289 Node* if_truei = ExpectPeeled(inner.if_true, peeled); | |
| 290 Node* if_falsei = ExpectPeeled(inner.exit, peeled); | |
| 291 | |
| 292 EXPECT_THAT(bri, IsBranch(p0, ExpectPeeled(inner.loop, peeled))); | |
| 293 EXPECT_THAT(if_truei, IsIfTrue(bri)); | |
| 294 EXPECT_THAT(if_falsei, IsIfFalse(bri)); | |
| 295 | |
| 296 EXPECT_THAT(outer.loop, IsLoop(start(), IsMerge(inner.exit, if_falsei))); | |
| 297 EXPECT_THAT(peeled->map(c.add), IsInt32Add(c.base, c.inc)); | |
| 298 | |
| 299 Node* back = phi->InputAt(1); | |
| 300 EXPECT_THAT(back, IsPhi(kMachAnyTagged, c.phi, c.base, | |
| 301 IsMerge(inner.exit, if_falsei))); | |
| 302 | |
| 303 EXPECT_THAT(phi, | |
| 304 IsPhi(kMachAnyTagged, IsInt32Constant(11), back, outer.loop)); | |
| 305 | |
| 306 EXPECT_THAT(r, IsReturn(phi, start(), outer.exit)); | |
| 307 } | |
| 308 | |
| 309 | |
| 310 TEST_F(LoopPeelingTest, TwoBackedgeLoop) { | |
| 311 Node* p0 = Parameter(0); | |
| 312 Node* loop = graph()->NewNode(common()->Loop(3), start(), start(), start()); | |
| 313 Branch b1 = NewBranch(p0, loop); | |
| 314 Branch b2 = NewBranch(p0, b1.if_true); | |
| 315 | |
| 316 loop->ReplaceInput(1, b2.if_true); | |
| 317 loop->ReplaceInput(2, b2.if_false); | |
| 318 | |
| 319 Node* r = InsertReturn(p0, start(), b1.if_false); | |
| 320 | |
| 321 PeeledIteration* peeled = PeelOne(); | |
| 322 | |
| 323 Node* b1b = ExpectPeeled(b1.branch, peeled); | |
| 324 Node* b1t = ExpectPeeled(b1.if_true, peeled); | |
| 325 Node* b1f = ExpectPeeled(b1.if_false, peeled); | |
| 326 | |
| 327 EXPECT_THAT(b1b, IsBranch(p0, start())); | |
| 328 EXPECT_THAT(ExpectPeeled(b1.if_true, peeled), IsIfTrue(b1b)); | |
| 329 EXPECT_THAT(b1f, IsIfFalse(b1b)); | |
| 330 | |
| 331 Node* b2b = ExpectPeeled(b2.branch, peeled); | |
| 332 Node* b2t = ExpectPeeled(b2.if_true, peeled); | |
| 333 Node* b2f = ExpectPeeled(b2.if_false, peeled); | |
| 334 | |
| 335 EXPECT_THAT(b2b, IsBranch(p0, b1t)); | |
| 336 EXPECT_THAT(b2t, IsIfTrue(b2b)); | |
| 337 EXPECT_THAT(b2f, IsIfFalse(b2b)); | |
| 338 | |
| 339 EXPECT_THAT(loop, IsLoop(IsMerge(b2t, b2f), b2.if_true, b2.if_false)); | |
| 340 EXPECT_THAT(r, IsReturn(p0, start(), IsMerge(b1.if_false, b1f))); | |
| 341 } | |
| 342 | |
| 343 | |
| 344 TEST_F(LoopPeelingTest, TwoBackedgeLoopWithPhi) { | |
| 345 Node* p0 = Parameter(0); | |
| 346 Node* loop = graph()->NewNode(common()->Loop(3), start(), start(), start()); | |
| 347 Branch b1 = NewBranch(p0, loop); | |
| 348 Branch b2 = NewBranch(p0, b1.if_true); | |
| 349 Node* phi = | |
| 350 graph()->NewNode(common()->Phi(kMachAnyTagged, 3), Int32Constant(0), | |
| 351 Int32Constant(1), Int32Constant(2), loop); | |
| 352 | |
| 353 loop->ReplaceInput(1, b2.if_true); | |
| 354 loop->ReplaceInput(2, b2.if_false); | |
| 355 | |
| 356 Node* r = InsertReturn(phi, start(), b1.if_false); | |
| 357 | |
| 358 PeeledIteration* peeled = PeelOne(); | |
| 359 | |
| 360 Node* b1b = ExpectPeeled(b1.branch, peeled); | |
| 361 Node* b1t = ExpectPeeled(b1.if_true, peeled); | |
| 362 Node* b1f = ExpectPeeled(b1.if_false, peeled); | |
| 363 | |
| 364 EXPECT_THAT(b1b, IsBranch(p0, start())); | |
| 365 EXPECT_THAT(ExpectPeeled(b1.if_true, peeled), IsIfTrue(b1b)); | |
| 366 EXPECT_THAT(b1f, IsIfFalse(b1b)); | |
| 367 | |
| 368 Node* b2b = ExpectPeeled(b2.branch, peeled); | |
| 369 Node* b2t = ExpectPeeled(b2.if_true, peeled); | |
| 370 Node* b2f = ExpectPeeled(b2.if_false, peeled); | |
| 371 | |
| 372 EXPECT_THAT(b2b, IsBranch(p0, b1t)); | |
| 373 EXPECT_THAT(b2t, IsIfTrue(b2b)); | |
| 374 EXPECT_THAT(b2f, IsIfFalse(b2b)); | |
| 375 | |
| 376 EXPECT_THAT(loop, IsLoop(IsMerge(b2t, b2f), b2.if_true, b2.if_false)); | |
| 377 | |
| 378 EXPECT_THAT( | |
| 379 phi, IsPhi(kMachAnyTagged, IsPhi(kMachAnyTagged, IsInt32Constant(1), | |
| 380 IsInt32Constant(2), IsMerge(b2t, b2f)), | |
| 381 IsInt32Constant(1), IsInt32Constant(2), loop)); | |
| 382 | |
| 383 Capture<Node*> merge; | |
| 384 EXPECT_THAT( | |
| 385 r, IsReturn(IsPhi(kMachAnyTagged, phi, IsInt32Constant(0), | |
| 386 AllOf(CaptureEq(&merge), IsMerge(b1.if_false, b1f))), | |
| 387 start(), CaptureEq(&merge))); | |
| 388 } | |
| 389 | |
| 390 | |
| 391 TEST_F(LoopPeelingTest, TwoBackedgeLoopWithCounter) { | |
| 392 Node* p0 = Parameter(0); | |
| 393 Node* loop = graph()->NewNode(common()->Loop(3), start(), start(), start()); | |
| 394 Branch b1 = NewBranch(p0, loop); | |
| 395 Branch b2 = NewBranch(p0, b1.if_true); | |
| 396 Node* phi = | |
| 397 graph()->NewNode(common()->Phi(kMachAnyTagged, 3), Int32Constant(0), | |
| 398 Int32Constant(1), Int32Constant(2), loop); | |
| 399 | |
| 400 phi->ReplaceInput( | |
| 401 1, graph()->NewNode(machine()->Int32Add(), phi, Int32Constant(1))); | |
| 402 phi->ReplaceInput( | |
| 403 2, graph()->NewNode(machine()->Int32Add(), phi, Int32Constant(2))); | |
| 404 | |
| 405 loop->ReplaceInput(1, b2.if_true); | |
| 406 loop->ReplaceInput(2, b2.if_false); | |
| 407 | |
| 408 Node* r = InsertReturn(phi, start(), b1.if_false); | |
| 409 | |
| 410 PeeledIteration* peeled = PeelOne(); | |
| 411 | |
| 412 Node* b1b = ExpectPeeled(b1.branch, peeled); | |
| 413 Node* b1t = ExpectPeeled(b1.if_true, peeled); | |
| 414 Node* b1f = ExpectPeeled(b1.if_false, peeled); | |
| 415 | |
| 416 EXPECT_THAT(b1b, IsBranch(p0, start())); | |
| 417 EXPECT_THAT(ExpectPeeled(b1.if_true, peeled), IsIfTrue(b1b)); | |
| 418 EXPECT_THAT(b1f, IsIfFalse(b1b)); | |
| 419 | |
| 420 Node* b2b = ExpectPeeled(b2.branch, peeled); | |
| 421 Node* b2t = ExpectPeeled(b2.if_true, peeled); | |
| 422 Node* b2f = ExpectPeeled(b2.if_false, peeled); | |
| 423 | |
| 424 EXPECT_THAT(b2b, IsBranch(p0, b1t)); | |
| 425 EXPECT_THAT(b2t, IsIfTrue(b2b)); | |
| 426 EXPECT_THAT(b2f, IsIfFalse(b2b)); | |
| 427 | |
| 428 Capture<Node*> entry; | |
| 429 EXPECT_THAT(loop, IsLoop(AllOf(CaptureEq(&entry), IsMerge(b2t, b2f)), | |
| 430 b2.if_true, b2.if_false)); | |
| 431 | |
| 432 Node* eval = phi->InputAt(0); | |
| 433 | |
| 434 EXPECT_THAT(eval, IsPhi(kMachAnyTagged, | |
| 435 IsInt32Add(IsInt32Constant(0), IsInt32Constant(1)), | |
| 436 IsInt32Add(IsInt32Constant(0), IsInt32Constant(2)), | |
| 437 CaptureEq(&entry))); | |
| 438 | |
| 439 EXPECT_THAT(phi, | |
| 440 IsPhi(kMachAnyTagged, eval, IsInt32Add(phi, IsInt32Constant(1)), | |
| 441 IsInt32Add(phi, IsInt32Constant(2)), loop)); | |
| 442 | |
| 443 Capture<Node*> merge; | |
| 444 EXPECT_THAT( | |
| 445 r, IsReturn(IsPhi(kMachAnyTagged, phi, IsInt32Constant(0), | |
| 446 AllOf(CaptureEq(&merge), IsMerge(b1.if_false, b1f))), | |
| 447 start(), CaptureEq(&merge))); | |
| 448 } | |
| 449 | |
| 450 | |
| 451 } // namespace compiler | |
| 452 } // namespace internal | |
| 453 } // namespace v8 | |
| OLD | NEW |