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

Side by Side Diff: test/cctest/compiler/test-jump-threading.cc

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

Powered by Google App Engine
This is Rietveld 408576698