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

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

Powered by Google App Engine
This is Rietveld 408576698