Line data Source code
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/backend/instruction-codes.h"
6 : #include "src/compiler/backend/instruction.h"
7 : #include "src/compiler/backend/jump-threading.h"
8 : #include "src/source-position.h"
9 : #include "test/cctest/cctest.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 : namespace compiler {
14 :
15 2370 : class TestCode : public HandleAndZoneScope {
16 : public:
17 1185 : TestCode()
18 : : HandleAndZoneScope(),
19 : blocks_(main_zone()),
20 : sequence_(main_isolate(), main_zone(), &blocks_),
21 : rpo_number_(RpoNumber::FromInt(0)),
22 2370 : current_(nullptr) {}
23 :
24 : ZoneVector<InstructionBlock*> blocks_;
25 : InstructionSequence sequence_;
26 : RpoNumber rpo_number_;
27 : InstructionBlock* current_;
28 :
29 5580 : int Jump(int target) {
30 5580 : Start();
31 5580 : InstructionOperand ops[] = {UseRpo(target)};
32 5580 : sequence_.AddInstruction(Instruction::New(main_zone(), kArchJmp, 0, nullptr,
33 5580 : 1, ops, 0, nullptr));
34 5580 : int pos = static_cast<int>(sequence_.instructions().size() - 1);
35 5580 : End();
36 5580 : return pos;
37 : }
38 : void Fallthru() {
39 130 : Start();
40 130 : End();
41 : }
42 360 : int Branch(int ttarget, int ftarget) {
43 360 : Start();
44 720 : InstructionOperand ops[] = {UseRpo(ttarget), UseRpo(ftarget)};
45 : InstructionCode code = 119 | FlagsModeField::encode(kFlags_branch) |
46 : FlagsConditionField::encode(kEqual);
47 360 : sequence_.AddInstruction(
48 360 : Instruction::New(main_zone(), code, 0, nullptr, 2, ops, 0, nullptr));
49 360 : int pos = static_cast<int>(sequence_.instructions().size() - 1);
50 360 : End();
51 360 : return pos;
52 : }
53 180 : void Nop() {
54 180 : Start();
55 180 : sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
56 180 : }
57 10 : void RedundantMoves() {
58 10 : Start();
59 10 : sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
60 10 : int index = static_cast<int>(sequence_.instructions().size()) - 1;
61 10 : AddGapMove(index, AllocatedOperand(LocationOperand::REGISTER,
62 : MachineRepresentation::kWord32, 13),
63 : AllocatedOperand(LocationOperand::REGISTER,
64 10 : MachineRepresentation::kWord32, 13));
65 10 : }
66 25 : void NonRedundantMoves() {
67 25 : Start();
68 25 : sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
69 25 : int index = static_cast<int>(sequence_.instructions().size()) - 1;
70 25 : AddGapMove(index, ConstantOperand(11),
71 : AllocatedOperand(LocationOperand::REGISTER,
72 25 : MachineRepresentation::kWord32, 11));
73 25 : }
74 230 : void Other() {
75 230 : Start();
76 230 : sequence_.AddInstruction(Instruction::New(main_zone(), 155));
77 230 : }
78 7200 : void End() {
79 7200 : Start();
80 7200 : int end = static_cast<int>(sequence_.instructions().size());
81 7200 : if (current_->code_start() == end) { // Empty block. Insert a nop.
82 1240 : sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
83 : }
84 7200 : sequence_.EndBlock(current_->rpo_number());
85 7200 : current_ = nullptr;
86 7200 : rpo_number_ = RpoNumber::FromInt(rpo_number_.ToInt() + 1);
87 7200 : }
88 : InstructionOperand UseRpo(int num) {
89 6300 : return sequence_.AddImmediate(Constant(RpoNumber::FromInt(num)));
90 : }
91 13730 : void Start(bool deferred = false) {
92 13730 : if (current_ == nullptr) {
93 : current_ = new (main_zone())
94 14400 : InstructionBlock(main_zone(), rpo_number_, RpoNumber::Invalid(),
95 28800 : RpoNumber::Invalid(), deferred, false);
96 7200 : blocks_.push_back(current_);
97 7200 : sequence_.StartBlock(rpo_number_);
98 : }
99 13730 : }
100 15 : void Defer() {
101 15 : CHECK_NULL(current_);
102 15 : Start(true);
103 15 : }
104 35 : void AddGapMove(int index, const InstructionOperand& from,
105 : const InstructionOperand& to) {
106 : sequence_.InstructionAt(index)
107 : ->GetOrCreateParallelMove(Instruction::START, main_zone())
108 : ->AddMove(from, to);
109 35 : }
110 : };
111 :
112 :
113 1150 : void VerifyForwarding(TestCode& code, int count, int* expected) {
114 2300 : v8::internal::AccountingAllocator allocator;
115 2300 : Zone local_zone(&allocator, ZONE_NAME);
116 : ZoneVector<RpoNumber> result(&local_zone);
117 1150 : JumpThreading::ComputeForwarding(&local_zone, result, &code.sequence_, true);
118 :
119 1150 : CHECK(count == static_cast<int>(result.size()));
120 15240 : for (int i = 0; i < count; i++) {
121 14090 : CHECK(expected[i] == result[i].ToInt());
122 : }
123 1150 : }
124 :
125 :
126 26644 : TEST(FwEmpty1) {
127 5 : TestCode code;
128 :
129 : // B0
130 5 : code.Jump(1);
131 : // B1
132 5 : code.Jump(2);
133 : // B2
134 5 : code.End();
135 :
136 : static int expected[] = {2, 2, 2};
137 5 : VerifyForwarding(code, 3, expected);
138 5 : }
139 :
140 :
141 26644 : TEST(FwEmptyN) {
142 95 : for (int i = 0; i < 9; i++) {
143 45 : TestCode code;
144 :
145 : // B0
146 45 : code.Jump(1);
147 : // B1
148 225 : for (int j = 0; j < i; j++) code.Nop();
149 45 : code.Jump(2);
150 : // B2
151 45 : code.End();
152 :
153 : static int expected[] = {2, 2, 2};
154 45 : VerifyForwarding(code, 3, expected);
155 : }
156 5 : }
157 :
158 :
159 26644 : TEST(FwNone1) {
160 5 : TestCode code;
161 :
162 : // B0
163 5 : code.End();
164 :
165 : static int expected[] = {0};
166 5 : VerifyForwarding(code, 1, expected);
167 5 : }
168 :
169 :
170 26644 : TEST(FwMoves1) {
171 5 : TestCode code;
172 :
173 : // B0
174 5 : code.RedundantMoves();
175 5 : code.End();
176 :
177 : static int expected[] = {0};
178 5 : VerifyForwarding(code, 1, expected);
179 5 : }
180 :
181 :
182 26644 : TEST(FwMoves2) {
183 5 : TestCode code;
184 :
185 : // B0
186 5 : code.RedundantMoves();
187 : code.Fallthru();
188 : // B1
189 5 : code.End();
190 :
191 : static int expected[] = {1, 1};
192 5 : VerifyForwarding(code, 2, expected);
193 5 : }
194 :
195 :
196 26644 : TEST(FwMoves2b) {
197 5 : TestCode code;
198 :
199 : // B0
200 5 : code.NonRedundantMoves();
201 : code.Fallthru();
202 : // B1
203 5 : code.End();
204 :
205 : static int expected[] = {0, 1};
206 5 : VerifyForwarding(code, 2, expected);
207 5 : }
208 :
209 :
210 26644 : TEST(FwOther2) {
211 5 : TestCode code;
212 :
213 : // B0
214 5 : code.Other();
215 : code.Fallthru();
216 : // B1
217 5 : code.End();
218 :
219 : static int expected[] = {0, 1};
220 5 : VerifyForwarding(code, 2, expected);
221 5 : }
222 :
223 :
224 26644 : TEST(FwNone2a) {
225 5 : TestCode code;
226 :
227 : // B0
228 : code.Fallthru();
229 : // B1
230 5 : code.End();
231 :
232 : static int expected[] = {1, 1};
233 5 : VerifyForwarding(code, 2, expected);
234 5 : }
235 :
236 :
237 26644 : TEST(FwNone2b) {
238 5 : TestCode code;
239 :
240 : // B0
241 5 : code.Jump(1);
242 : // B1
243 5 : code.End();
244 :
245 : static int expected[] = {1, 1};
246 5 : VerifyForwarding(code, 2, expected);
247 5 : }
248 :
249 :
250 26644 : TEST(FwLoop1) {
251 5 : TestCode code;
252 :
253 : // B0
254 5 : code.Jump(0);
255 :
256 : static int expected[] = {0};
257 5 : VerifyForwarding(code, 1, expected);
258 5 : }
259 :
260 :
261 26644 : TEST(FwLoop2) {
262 5 : TestCode code;
263 :
264 : // B0
265 : code.Fallthru();
266 : // B1
267 5 : code.Jump(0);
268 :
269 : static int expected[] = {0, 0};
270 5 : VerifyForwarding(code, 2, expected);
271 5 : }
272 :
273 :
274 26644 : TEST(FwLoop3) {
275 5 : TestCode code;
276 :
277 : // B0
278 : code.Fallthru();
279 : // B1
280 : code.Fallthru();
281 : // B2
282 5 : code.Jump(0);
283 :
284 : static int expected[] = {0, 0, 0};
285 5 : VerifyForwarding(code, 3, expected);
286 5 : }
287 :
288 :
289 26644 : TEST(FwLoop1b) {
290 5 : TestCode code;
291 :
292 : // B0
293 : code.Fallthru();
294 : // B1
295 5 : code.Jump(1);
296 :
297 : static int expected[] = {1, 1};
298 5 : VerifyForwarding(code, 2, expected);
299 5 : }
300 :
301 :
302 26644 : TEST(FwLoop2b) {
303 5 : TestCode code;
304 :
305 : // B0
306 : code.Fallthru();
307 : // B1
308 : code.Fallthru();
309 : // B2
310 5 : code.Jump(1);
311 :
312 : static int expected[] = {1, 1, 1};
313 5 : VerifyForwarding(code, 3, expected);
314 5 : }
315 :
316 :
317 26644 : TEST(FwLoop3b) {
318 5 : TestCode code;
319 :
320 : // B0
321 : code.Fallthru();
322 : // B1
323 : code.Fallthru();
324 : // B2
325 : code.Fallthru();
326 : // B3
327 5 : code.Jump(1);
328 :
329 : static int expected[] = {1, 1, 1, 1};
330 5 : VerifyForwarding(code, 4, expected);
331 5 : }
332 :
333 :
334 26644 : TEST(FwLoop2_1a) {
335 5 : TestCode code;
336 :
337 : // B0
338 : code.Fallthru();
339 : // B1
340 : code.Fallthru();
341 : // B2
342 : code.Fallthru();
343 : // B3
344 5 : code.Jump(1);
345 : // B4
346 5 : code.Jump(2);
347 :
348 : static int expected[] = {1, 1, 1, 1, 1};
349 5 : VerifyForwarding(code, 5, expected);
350 5 : }
351 :
352 :
353 26644 : TEST(FwLoop2_1b) {
354 5 : TestCode code;
355 :
356 : // B0
357 : code.Fallthru();
358 : // B1
359 : code.Fallthru();
360 : // B2
361 5 : code.Jump(4);
362 : // B3
363 5 : code.Jump(1);
364 : // B4
365 5 : code.Jump(2);
366 :
367 : static int expected[] = {2, 2, 2, 2, 2};
368 5 : VerifyForwarding(code, 5, expected);
369 5 : }
370 :
371 :
372 26644 : TEST(FwLoop2_1c) {
373 5 : TestCode code;
374 :
375 : // B0
376 : code.Fallthru();
377 : // B1
378 : code.Fallthru();
379 : // B2
380 5 : code.Jump(4);
381 : // B3
382 5 : code.Jump(2);
383 : // B4
384 5 : code.Jump(1);
385 :
386 : static int expected[] = {1, 1, 1, 1, 1};
387 5 : VerifyForwarding(code, 5, expected);
388 5 : }
389 :
390 :
391 26644 : TEST(FwLoop2_1d) {
392 5 : TestCode code;
393 :
394 : // B0
395 : code.Fallthru();
396 : // B1
397 : code.Fallthru();
398 : // B2
399 5 : code.Jump(1);
400 : // B3
401 5 : code.Jump(1);
402 : // B4
403 5 : code.Jump(1);
404 :
405 : static int expected[] = {1, 1, 1, 1, 1};
406 5 : VerifyForwarding(code, 5, expected);
407 5 : }
408 :
409 :
410 26644 : TEST(FwLoop3_1a) {
411 5 : TestCode code;
412 :
413 : // B0
414 : code.Fallthru();
415 : // B1
416 : code.Fallthru();
417 : // B2
418 : code.Fallthru();
419 : // B3
420 5 : code.Jump(2);
421 : // B4
422 5 : code.Jump(1);
423 : // B5
424 5 : code.Jump(0);
425 :
426 : static int expected[] = {2, 2, 2, 2, 2, 2};
427 5 : VerifyForwarding(code, 6, expected);
428 5 : }
429 :
430 :
431 26644 : TEST(FwDiamonds) {
432 25 : for (int i = 0; i < 2; i++) {
433 50 : for (int j = 0; j < 2; j++) {
434 20 : TestCode code;
435 : // B0
436 20 : code.Branch(1, 2);
437 : // B1
438 20 : if (i) code.Other();
439 20 : code.Jump(3);
440 : // B2
441 20 : if (j) code.Other();
442 20 : code.Jump(3);
443 : // B3
444 20 : code.End();
445 :
446 20 : int expected[] = {0, i ? 1 : 3, j ? 2 : 3, 3};
447 20 : VerifyForwarding(code, 4, expected);
448 : }
449 : }
450 5 : }
451 :
452 :
453 26644 : TEST(FwDiamonds2) {
454 25 : for (int i = 0; i < 2; i++) {
455 50 : for (int j = 0; j < 2; j++) {
456 100 : for (int k = 0; k < 2; k++) {
457 40 : TestCode code;
458 : // B0
459 40 : code.Branch(1, 2);
460 : // B1
461 40 : if (i) code.Other();
462 40 : code.Jump(3);
463 : // B2
464 40 : if (j) code.Other();
465 40 : code.Jump(3);
466 : // B3
467 40 : if (k) code.NonRedundantMoves();
468 40 : code.Jump(4);
469 : // B4
470 40 : code.End();
471 :
472 40 : int merge = k ? 3 : 4;
473 40 : int expected[] = {0, i ? 1 : merge, j ? 2 : merge, merge, 4};
474 40 : VerifyForwarding(code, 5, expected);
475 : }
476 : }
477 : }
478 5 : }
479 :
480 :
481 26644 : TEST(FwDoubleDiamonds) {
482 25 : for (int i = 0; i < 2; i++) {
483 50 : for (int j = 0; j < 2; j++) {
484 100 : for (int x = 0; x < 2; x++) {
485 200 : for (int y = 0; y < 2; y++) {
486 80 : TestCode code;
487 : // B0
488 80 : code.Branch(1, 2);
489 : // B1
490 80 : if (i) code.Other();
491 80 : code.Jump(3);
492 : // B2
493 80 : if (j) code.Other();
494 80 : code.Jump(3);
495 : // B3
496 80 : code.Branch(4, 5);
497 : // B4
498 80 : if (x) code.Other();
499 80 : code.Jump(6);
500 : // B5
501 80 : if (y) code.Other();
502 80 : code.Jump(6);
503 : // B6
504 80 : code.End();
505 :
506 : int expected[] = {0, i ? 1 : 3, j ? 2 : 3, 3,
507 80 : x ? 4 : 6, y ? 5 : 6, 6};
508 80 : VerifyForwarding(code, 7, expected);
509 : }
510 : }
511 : }
512 : }
513 5 : }
514 :
515 : template <int kSize>
516 2360 : void RunPermutationsRecursive(int outer[kSize], int start,
517 : void (*run)(int*, int)) {
518 : int permutation[kSize];
519 :
520 13350 : for (int i = 0; i < kSize; i++) permutation[i] = outer[i];
521 :
522 : int count = kSize - start;
523 2360 : if (count == 0) return run(permutation, kSize);
524 6170 : for (int i = start; i < kSize; i++) {
525 2340 : permutation[start] = outer[i];
526 2340 : permutation[i] = outer[start];
527 2340 : RunPermutationsRecursive<kSize>(permutation, start + 1, run);
528 2340 : permutation[i] = outer[i];
529 2340 : permutation[start] = outer[start];
530 : }
531 : }
532 :
533 :
534 : template <int kSize>
535 : void RunAllPermutations(void (*run)(int*, int)) {
536 : int permutation[kSize];
537 100 : for (int i = 0; i < kSize; i++) permutation[i] = i;
538 20 : RunPermutationsRecursive<kSize>(permutation, 0, run);
539 : }
540 :
541 :
542 0 : void PrintPermutation(int* permutation, int size) {
543 : printf("{ ");
544 0 : for (int i = 0; i < size; i++) {
545 0 : if (i > 0) printf(", ");
546 0 : printf("%d", permutation[i]);
547 : }
548 : printf(" }\n");
549 0 : }
550 :
551 :
552 0 : int find(int x, int* permutation, int size) {
553 27480 : for (int i = 0; i < size; i++) {
554 15450 : if (permutation[i] == x) return i;
555 : }
556 : return size;
557 : }
558 :
559 :
560 750 : void RunPermutedChain(int* permutation, int size) {
561 750 : TestCode code;
562 : int cur = -1;
563 7890 : for (int i = 0; i < size; i++) {
564 7140 : code.Jump(find(cur + 1, permutation, size) + 1);
565 3570 : cur = permutation[i];
566 : }
567 1500 : code.Jump(find(cur + 1, permutation, size) + 1);
568 750 : code.End();
569 :
570 750 : int expected[] = {size + 1, size + 1, size + 1, size + 1,
571 750 : size + 1, size + 1, size + 1};
572 750 : VerifyForwarding(code, size + 2, expected);
573 750 : }
574 :
575 :
576 26644 : TEST(FwPermuted_chain) {
577 : RunAllPermutations<3>(RunPermutedChain);
578 : RunAllPermutations<4>(RunPermutedChain);
579 : RunAllPermutations<5>(RunPermutedChain);
580 5 : }
581 :
582 :
583 120 : void RunPermutedDiamond(int* permutation, int size) {
584 120 : TestCode code;
585 120 : int br = 1 + find(0, permutation, size);
586 120 : code.Jump(br);
587 1080 : for (int i = 0; i < size; i++) {
588 480 : switch (permutation[i]) {
589 : case 0:
590 240 : code.Branch(1 + find(1, permutation, size),
591 120 : 1 + find(2, permutation, size));
592 120 : break;
593 : case 1:
594 120 : code.Jump(1 + find(3, permutation, size));
595 120 : break;
596 : case 2:
597 120 : code.Jump(1 + find(3, permutation, size));
598 120 : break;
599 : case 3:
600 120 : code.Jump(5);
601 120 : break;
602 : }
603 : }
604 120 : code.End();
605 :
606 120 : int expected[] = {br, 5, 5, 5, 5, 5};
607 120 : expected[br] = br;
608 120 : VerifyForwarding(code, 6, expected);
609 120 : }
610 :
611 :
612 26649 : TEST(FwPermuted_diamond) { RunAllPermutations<4>(RunPermutedDiamond); }
613 :
614 :
615 35 : void ApplyForwarding(TestCode& code, int size, int* forward) {
616 35 : code.sequence_.RecomputeAssemblyOrderForTesting();
617 : ZoneVector<RpoNumber> vector(code.main_zone());
618 345 : for (int i = 0; i < size; i++) {
619 310 : vector.push_back(RpoNumber::FromInt(forward[i]));
620 : }
621 35 : JumpThreading::ApplyForwarding(code.main_zone(), vector, &code.sequence_);
622 35 : }
623 :
624 :
625 60 : void CheckJump(TestCode& code, int pos, int target) {
626 : Instruction* instr = code.sequence_.InstructionAt(pos);
627 60 : CHECK_EQ(kArchJmp, instr->arch_opcode());
628 60 : CHECK_EQ(1, static_cast<int>(instr->InputCount()));
629 60 : CHECK_EQ(0, static_cast<int>(instr->OutputCount()));
630 60 : CHECK_EQ(0, static_cast<int>(instr->TempCount()));
631 120 : CHECK_EQ(target, code.sequence_.InputRpo(instr, 0).ToInt());
632 60 : }
633 :
634 :
635 35 : void CheckNop(TestCode& code, int pos) {
636 : Instruction* instr = code.sequence_.InstructionAt(pos);
637 35 : CHECK_EQ(kArchNop, instr->arch_opcode());
638 35 : CHECK_EQ(0, static_cast<int>(instr->InputCount()));
639 35 : CHECK_EQ(0, static_cast<int>(instr->OutputCount()));
640 35 : CHECK_EQ(0, static_cast<int>(instr->TempCount()));
641 35 : }
642 :
643 :
644 20 : void CheckBranch(TestCode& code, int pos, int t1, int t2) {
645 : Instruction* instr = code.sequence_.InstructionAt(pos);
646 20 : CHECK_EQ(2, static_cast<int>(instr->InputCount()));
647 20 : CHECK_EQ(0, static_cast<int>(instr->OutputCount()));
648 20 : CHECK_EQ(0, static_cast<int>(instr->TempCount()));
649 40 : CHECK_EQ(t1, code.sequence_.InputRpo(instr, 0).ToInt());
650 40 : CHECK_EQ(t2, code.sequence_.InputRpo(instr, 1).ToInt());
651 20 : }
652 :
653 :
654 35 : void CheckAssemblyOrder(TestCode& code, int size, int* expected) {
655 : int i = 0;
656 190 : for (auto const block : code.sequence_.instruction_blocks()) {
657 155 : CHECK_EQ(expected[i++], block->ao_number().ToInt());
658 : }
659 35 : }
660 :
661 :
662 26644 : TEST(Rewire1) {
663 5 : TestCode code;
664 :
665 : // B0
666 5 : int j1 = code.Jump(1);
667 : // B1
668 5 : int j2 = code.Jump(2);
669 : // B2
670 5 : code.End();
671 :
672 : static int forward[] = {2, 2, 2};
673 5 : ApplyForwarding(code, 3, forward);
674 5 : CheckJump(code, j1, 2);
675 5 : CheckNop(code, j2);
676 :
677 : static int assembly[] = {0, 1, 1};
678 5 : CheckAssemblyOrder(code, 3, assembly);
679 5 : }
680 :
681 :
682 26644 : TEST(Rewire1_deferred) {
683 5 : TestCode code;
684 :
685 : // B0
686 5 : int j1 = code.Jump(1);
687 : // B1
688 5 : int j2 = code.Jump(2);
689 : // B2
690 5 : code.Defer();
691 5 : int j3 = code.Jump(3);
692 : // B3
693 5 : code.End();
694 :
695 : static int forward[] = {3, 3, 3, 3};
696 5 : ApplyForwarding(code, 4, forward);
697 5 : CheckJump(code, j1, 3);
698 5 : CheckNop(code, j2);
699 5 : CheckNop(code, j3);
700 :
701 : static int assembly[] = {0, 1, 2, 1};
702 5 : CheckAssemblyOrder(code, 4, assembly);
703 5 : }
704 :
705 :
706 26644 : TEST(Rewire2_deferred) {
707 5 : TestCode code;
708 :
709 : // B0
710 5 : code.Other();
711 5 : int j1 = code.Jump(1);
712 : // B1
713 5 : code.Defer();
714 : code.Fallthru();
715 : // B2
716 5 : code.Defer();
717 5 : int j2 = code.Jump(3);
718 : // B3
719 5 : code.End();
720 :
721 : static int forward[] = {0, 1, 2, 3};
722 5 : ApplyForwarding(code, 4, forward);
723 5 : CheckJump(code, j1, 1);
724 5 : CheckJump(code, j2, 3);
725 :
726 : static int assembly[] = {0, 2, 3, 1};
727 5 : CheckAssemblyOrder(code, 4, assembly);
728 5 : }
729 :
730 :
731 26644 : TEST(Rewire_diamond) {
732 25 : for (int i = 0; i < 2; i++) {
733 50 : for (int j = 0; j < 2; j++) {
734 20 : TestCode code;
735 : // B0
736 20 : int j1 = code.Jump(1);
737 : // B1
738 20 : int b1 = code.Branch(2, 3);
739 : // B2
740 20 : int j2 = code.Jump(4);
741 : // B3
742 20 : int j3 = code.Jump(4);
743 : // B5
744 20 : code.End();
745 :
746 20 : int forward[] = {0, 1, i ? 4 : 2, j ? 4 : 3, 4};
747 20 : ApplyForwarding(code, 5, forward);
748 20 : CheckJump(code, j1, 1);
749 20 : CheckBranch(code, b1, i ? 4 : 2, j ? 4 : 3);
750 20 : if (i) {
751 10 : CheckNop(code, j2);
752 : } else {
753 10 : CheckJump(code, j2, 4);
754 : }
755 20 : if (j) {
756 10 : CheckNop(code, j3);
757 : } else {
758 10 : CheckJump(code, j3, 4);
759 : }
760 :
761 20 : int assembly[] = {0, 1, 2, 3, 4};
762 20 : if (i) {
763 30 : for (int k = 3; k < 5; k++) assembly[k]--;
764 : }
765 20 : if (j) {
766 20 : for (int k = 4; k < 5; k++) assembly[k]--;
767 : }
768 20 : CheckAssemblyOrder(code, 5, assembly);
769 : }
770 : }
771 5 : }
772 :
773 : } // namespace compiler
774 : } // namespace internal
775 79917 : } // namespace v8
|