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

Side by Side Diff: test/unittests/compiler/regalloc/register-allocator-unittest.cc

Issue 2585583006: Move register allocation unittests and constrain owners (Closed)
Patch Set: Created 4 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
1 // Copyright 2014 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/pipeline.h" 5 #include "src/compiler/pipeline.h"
6 #include "test/unittests/compiler/instruction-sequence-unittest.h" 6 #include "test/unittests/compiler/instruction-sequence-unittest.h"
7 7
8 namespace v8 { 8 namespace v8 {
9 namespace internal { 9 namespace internal {
10 namespace compiler { 10 namespace compiler {
11 11
12
13 namespace { 12 namespace {
14 13
15 // We can't just use the size of the moves collection, because of 14 // We can't just use the size of the moves collection, because of
16 // redundant moves which need to be discounted. 15 // redundant moves which need to be discounted.
17 int GetMoveCount(const ParallelMove& moves) { 16 int GetMoveCount(const ParallelMove& moves) {
18 int move_count = 0; 17 int move_count = 0;
19 for (auto move : moves) { 18 for (auto move : moves) {
20 if (move->IsEliminated() || move->IsRedundant()) continue; 19 if (move->IsEliminated() || move->IsRedundant()) continue;
21 ++move_count; 20 ++move_count;
22 } 21 }
23 return move_count; 22 return move_count;
24 } 23 }
25 24
26
27 bool AreOperandsOfSameType( 25 bool AreOperandsOfSameType(
28 const AllocatedOperand& op, 26 const AllocatedOperand& op,
29 const InstructionSequenceTest::TestOperand& test_op) { 27 const InstructionSequenceTest::TestOperand& test_op) {
30 bool test_op_is_reg = 28 bool test_op_is_reg =
31 (test_op.type_ == 29 (test_op.type_ ==
32 InstructionSequenceTest::TestOperandType::kFixedRegister || 30 InstructionSequenceTest::TestOperandType::kFixedRegister ||
33 test_op.type_ == InstructionSequenceTest::TestOperandType::kRegister); 31 test_op.type_ == InstructionSequenceTest::TestOperandType::kRegister);
34 32
35 return (op.IsRegister() && test_op_is_reg) || 33 return (op.IsRegister() && test_op_is_reg) ||
36 (op.IsStackSlot() && !test_op_is_reg); 34 (op.IsStackSlot() && !test_op_is_reg);
37 } 35 }
38 36
39
40 bool AllocatedOperandMatches( 37 bool AllocatedOperandMatches(
41 const AllocatedOperand& op, 38 const AllocatedOperand& op,
42 const InstructionSequenceTest::TestOperand& test_op) { 39 const InstructionSequenceTest::TestOperand& test_op) {
43 return AreOperandsOfSameType(op, test_op) && 40 return AreOperandsOfSameType(op, test_op) &&
44 ((op.IsRegister() ? op.GetRegister().code() : op.index()) == 41 ((op.IsRegister() ? op.GetRegister().code() : op.index()) ==
45 test_op.value_ || 42 test_op.value_ ||
46 test_op.value_ == InstructionSequenceTest::kNoValue); 43 test_op.value_ == InstructionSequenceTest::kNoValue);
47 } 44 }
48 45
49
50 int GetParallelMoveCount(int instr_index, Instruction::GapPosition gap_pos, 46 int GetParallelMoveCount(int instr_index, Instruction::GapPosition gap_pos,
51 const InstructionSequence* sequence) { 47 const InstructionSequence* sequence) {
52 const ParallelMove* moves = 48 const ParallelMove* moves =
53 sequence->InstructionAt(instr_index)->GetParallelMove(gap_pos); 49 sequence->InstructionAt(instr_index)->GetParallelMove(gap_pos);
54 if (moves == nullptr) return 0; 50 if (moves == nullptr) return 0;
55 return GetMoveCount(*moves); 51 return GetMoveCount(*moves);
56 } 52 }
57 53
58
59 bool IsParallelMovePresent(int instr_index, Instruction::GapPosition gap_pos, 54 bool IsParallelMovePresent(int instr_index, Instruction::GapPosition gap_pos,
60 const InstructionSequence* sequence, 55 const InstructionSequence* sequence,
61 const InstructionSequenceTest::TestOperand& src, 56 const InstructionSequenceTest::TestOperand& src,
62 const InstructionSequenceTest::TestOperand& dest) { 57 const InstructionSequenceTest::TestOperand& dest) {
63 const ParallelMove* moves = 58 const ParallelMove* moves =
64 sequence->InstructionAt(instr_index)->GetParallelMove(gap_pos); 59 sequence->InstructionAt(instr_index)->GetParallelMove(gap_pos);
65 EXPECT_NE(nullptr, moves); 60 EXPECT_NE(nullptr, moves);
66 61
67 bool found_match = false; 62 bool found_match = false;
68 for (auto move : *moves) { 63 for (auto move : *moves) {
69 if (move->IsEliminated() || move->IsRedundant()) continue; 64 if (move->IsEliminated() || move->IsRedundant()) continue;
70 if (AllocatedOperandMatches(AllocatedOperand::cast(move->source()), src) && 65 if (AllocatedOperandMatches(AllocatedOperand::cast(move->source()), src) &&
71 AllocatedOperandMatches(AllocatedOperand::cast(move->destination()), 66 AllocatedOperandMatches(AllocatedOperand::cast(move->destination()),
72 dest)) { 67 dest)) {
73 found_match = true; 68 found_match = true;
74 break; 69 break;
75 } 70 }
76 } 71 }
77 return found_match; 72 return found_match;
78 } 73 }
79 74
80 } // namespace 75 } // namespace
81 76
82
83 class RegisterAllocatorTest : public InstructionSequenceTest { 77 class RegisterAllocatorTest : public InstructionSequenceTest {
84 public: 78 public:
85 void Allocate() { 79 void Allocate() {
86 WireBlocks(); 80 WireBlocks();
87 Pipeline::AllocateRegistersForTesting(config(), sequence(), true); 81 Pipeline::AllocateRegistersForTesting(config(), sequence(), true);
88 } 82 }
89 }; 83 };
90 84
91
92 TEST_F(RegisterAllocatorTest, CanAllocateThreeRegisters) { 85 TEST_F(RegisterAllocatorTest, CanAllocateThreeRegisters) {
93 // return p0 + p1; 86 // return p0 + p1;
94 StartBlock(); 87 StartBlock();
95 auto a_reg = Parameter(); 88 auto a_reg = Parameter();
96 auto b_reg = Parameter(); 89 auto b_reg = Parameter();
97 auto c_reg = EmitOI(Reg(1), Reg(a_reg, 1), Reg(b_reg, 0)); 90 auto c_reg = EmitOI(Reg(1), Reg(a_reg, 1), Reg(b_reg, 0));
98 Return(c_reg); 91 Return(c_reg);
99 EndBlock(Last()); 92 EndBlock(Last());
100 93
101 Allocate(); 94 Allocate();
(...skipping 27 matching lines...) Expand all
129 auto ipp = EmitOI(Same(), Reg(phi), Use(DefineConstant())); 122 auto ipp = EmitOI(Same(), Reg(phi), Use(DefineConstant()));
130 SetInput(phi, 1, ipp); 123 SetInput(phi, 1, ipp);
131 EndBlock(Jump(0)); 124 EndBlock(Jump(0));
132 125
133 EndLoop(); 126 EndLoop();
134 } 127 }
135 128
136 Allocate(); 129 Allocate();
137 } 130 }
138 131
139
140 TEST_F(RegisterAllocatorTest, SimpleBranch) { 132 TEST_F(RegisterAllocatorTest, SimpleBranch) {
141 // return i ? K1 : K2 133 // return i ? K1 : K2
142 StartBlock(); 134 StartBlock();
143 auto i = DefineConstant(); 135 auto i = DefineConstant();
144 EndBlock(Branch(Reg(i), 1, 2)); 136 EndBlock(Branch(Reg(i), 1, 2));
145 137
146 StartBlock(); 138 StartBlock();
147 Return(DefineConstant()); 139 Return(DefineConstant());
148 EndBlock(Last()); 140 EndBlock(Last());
149 141
150 StartBlock(); 142 StartBlock();
151 Return(DefineConstant()); 143 Return(DefineConstant());
152 EndBlock(Last()); 144 EndBlock(Last());
153 145
154 Allocate(); 146 Allocate();
155 } 147 }
156 148
157
158 TEST_F(RegisterAllocatorTest, SimpleDiamond) { 149 TEST_F(RegisterAllocatorTest, SimpleDiamond) {
159 // return p0 ? p0 : p0 150 // return p0 ? p0 : p0
160 StartBlock(); 151 StartBlock();
161 auto param = Parameter(); 152 auto param = Parameter();
162 EndBlock(Branch(Reg(param), 1, 2)); 153 EndBlock(Branch(Reg(param), 1, 2));
163 154
164 StartBlock(); 155 StartBlock();
165 EndBlock(Jump(2)); 156 EndBlock(Jump(2));
166 157
167 StartBlock(); 158 StartBlock();
168 EndBlock(Jump(1)); 159 EndBlock(Jump(1));
169 160
170 StartBlock(); 161 StartBlock();
171 Return(param); 162 Return(param);
172 EndBlock(); 163 EndBlock();
173 164
174 Allocate(); 165 Allocate();
175 } 166 }
176 167
177
178 TEST_F(RegisterAllocatorTest, SimpleDiamondPhi) { 168 TEST_F(RegisterAllocatorTest, SimpleDiamondPhi) {
179 // return i ? K1 : K2 169 // return i ? K1 : K2
180 StartBlock(); 170 StartBlock();
181 EndBlock(Branch(Reg(DefineConstant()), 1, 2)); 171 EndBlock(Branch(Reg(DefineConstant()), 1, 2));
182 172
183 StartBlock(); 173 StartBlock();
184 auto t_val = DefineConstant(); 174 auto t_val = DefineConstant();
185 EndBlock(Jump(2)); 175 EndBlock(Jump(2));
186 176
187 StartBlock(); 177 StartBlock();
188 auto f_val = DefineConstant(); 178 auto f_val = DefineConstant();
189 EndBlock(Jump(1)); 179 EndBlock(Jump(1));
190 180
191 StartBlock(); 181 StartBlock();
192 Return(Reg(Phi(t_val, f_val))); 182 Return(Reg(Phi(t_val, f_val)));
193 EndBlock(); 183 EndBlock();
194 184
195 Allocate(); 185 Allocate();
196 } 186 }
197 187
198
199 TEST_F(RegisterAllocatorTest, DiamondManyPhis) { 188 TEST_F(RegisterAllocatorTest, DiamondManyPhis) {
200 const int kPhis = kDefaultNRegs * 2; 189 const int kPhis = kDefaultNRegs * 2;
201 190
202 StartBlock(); 191 StartBlock();
203 EndBlock(Branch(Reg(DefineConstant()), 1, 2)); 192 EndBlock(Branch(Reg(DefineConstant()), 1, 2));
204 193
205 StartBlock(); 194 StartBlock();
206 VReg t_vals[kPhis]; 195 VReg t_vals[kPhis];
207 for (int i = 0; i < kPhis; ++i) { 196 for (int i = 0; i < kPhis; ++i) {
208 t_vals[i] = DefineConstant(); 197 t_vals[i] = DefineConstant();
(...skipping 11 matching lines...) Expand all
220 TestOperand merged[kPhis]; 209 TestOperand merged[kPhis];
221 for (int i = 0; i < kPhis; ++i) { 210 for (int i = 0; i < kPhis; ++i) {
222 merged[i] = Use(Phi(t_vals[i], f_vals[i])); 211 merged[i] = Use(Phi(t_vals[i], f_vals[i]));
223 } 212 }
224 Return(EmitCall(Slot(-1), kPhis, merged)); 213 Return(EmitCall(Slot(-1), kPhis, merged));
225 EndBlock(); 214 EndBlock();
226 215
227 Allocate(); 216 Allocate();
228 } 217 }
229 218
230
231 TEST_F(RegisterAllocatorTest, DoubleDiamondManyRedundantPhis) { 219 TEST_F(RegisterAllocatorTest, DoubleDiamondManyRedundantPhis) {
232 const int kPhis = kDefaultNRegs * 2; 220 const int kPhis = kDefaultNRegs * 2;
233 221
234 // First diamond. 222 // First diamond.
235 StartBlock(); 223 StartBlock();
236 VReg vals[kPhis]; 224 VReg vals[kPhis];
237 for (int i = 0; i < kPhis; ++i) { 225 for (int i = 0; i < kPhis; ++i) {
238 vals[i] = Parameter(Slot(-1 - i)); 226 vals[i] = Parameter(Slot(-1 - i));
239 } 227 }
240 EndBlock(Branch(Reg(DefineConstant()), 1, 2)); 228 EndBlock(Branch(Reg(DefineConstant()), 1, 2));
(...skipping 18 matching lines...) Expand all
259 TestOperand merged[kPhis]; 247 TestOperand merged[kPhis];
260 for (int i = 0; i < kPhis; ++i) { 248 for (int i = 0; i < kPhis; ++i) {
261 merged[i] = Use(Phi(vals[i], vals[i])); 249 merged[i] = Use(Phi(vals[i], vals[i]));
262 } 250 }
263 Return(EmitCall(Reg(0), kPhis, merged)); 251 Return(EmitCall(Reg(0), kPhis, merged));
264 EndBlock(); 252 EndBlock();
265 253
266 Allocate(); 254 Allocate();
267 } 255 }
268 256
269
270 TEST_F(RegisterAllocatorTest, RegressionPhisNeedTooManyRegisters) { 257 TEST_F(RegisterAllocatorTest, RegressionPhisNeedTooManyRegisters) {
271 const size_t kNumRegs = 3; 258 const size_t kNumRegs = 3;
272 const size_t kParams = kNumRegs + 1; 259 const size_t kParams = kNumRegs + 1;
273 // Override number of registers. 260 // Override number of registers.
274 SetNumRegs(kNumRegs, kNumRegs); 261 SetNumRegs(kNumRegs, kNumRegs);
275 262
276 StartBlock(); 263 StartBlock();
277 auto constant = DefineConstant(); 264 auto constant = DefineConstant();
278 VReg parameters[kParams]; 265 VReg parameters[kParams];
279 for (size_t i = 0; i < arraysize(parameters); ++i) { 266 for (size_t i = 0; i < arraysize(parameters); ++i) {
(...skipping 28 matching lines...) Expand all
308 EndLoop(); 295 EndLoop();
309 } 296 }
310 297
311 StartBlock(); 298 StartBlock();
312 Return(DefineConstant()); 299 Return(DefineConstant());
313 EndBlock(); 300 EndBlock();
314 301
315 Allocate(); 302 Allocate();
316 } 303 }
317 304
318
319 TEST_F(RegisterAllocatorTest, SpillPhi) { 305 TEST_F(RegisterAllocatorTest, SpillPhi) {
320 StartBlock(); 306 StartBlock();
321 EndBlock(Branch(Imm(), 1, 2)); 307 EndBlock(Branch(Imm(), 1, 2));
322 308
323 StartBlock(); 309 StartBlock();
324 auto left = Define(Reg(0)); 310 auto left = Define(Reg(0));
325 EndBlock(Jump(2)); 311 EndBlock(Jump(2));
326 312
327 StartBlock(); 313 StartBlock();
328 auto right = Define(Reg(0)); 314 auto right = Define(Reg(0));
329 EndBlock(); 315 EndBlock();
330 316
331 StartBlock(); 317 StartBlock();
332 auto phi = Phi(left, right); 318 auto phi = Phi(left, right);
333 EmitCall(Slot(-1)); 319 EmitCall(Slot(-1));
334 Return(Reg(phi)); 320 Return(Reg(phi));
335 EndBlock(); 321 EndBlock();
336 322
337 Allocate(); 323 Allocate();
338 } 324 }
339 325
340
341 TEST_F(RegisterAllocatorTest, MoveLotsOfConstants) { 326 TEST_F(RegisterAllocatorTest, MoveLotsOfConstants) {
342 StartBlock(); 327 StartBlock();
343 VReg constants[kDefaultNRegs]; 328 VReg constants[kDefaultNRegs];
344 for (size_t i = 0; i < arraysize(constants); ++i) { 329 for (size_t i = 0; i < arraysize(constants); ++i) {
345 constants[i] = DefineConstant(); 330 constants[i] = DefineConstant();
346 } 331 }
347 TestOperand call_ops[kDefaultNRegs * 2]; 332 TestOperand call_ops[kDefaultNRegs * 2];
348 for (int i = 0; i < kDefaultNRegs; ++i) { 333 for (int i = 0; i < kDefaultNRegs; ++i) {
349 call_ops[i] = Reg(constants[i], i); 334 call_ops[i] = Reg(constants[i], i);
350 } 335 }
351 for (int i = 0; i < kDefaultNRegs; ++i) { 336 for (int i = 0; i < kDefaultNRegs; ++i) {
352 call_ops[i + kDefaultNRegs] = Slot(constants[i], i); 337 call_ops[i + kDefaultNRegs] = Slot(constants[i], i);
353 } 338 }
354 EmitCall(Slot(-1), arraysize(call_ops), call_ops); 339 EmitCall(Slot(-1), arraysize(call_ops), call_ops);
355 EndBlock(Last()); 340 EndBlock(Last());
356 341
357 Allocate(); 342 Allocate();
358 } 343 }
359 344
360
361 TEST_F(RegisterAllocatorTest, SplitBeforeInstruction) { 345 TEST_F(RegisterAllocatorTest, SplitBeforeInstruction) {
362 const int kNumRegs = 6; 346 const int kNumRegs = 6;
363 SetNumRegs(kNumRegs, kNumRegs); 347 SetNumRegs(kNumRegs, kNumRegs);
364 348
365 StartBlock(); 349 StartBlock();
366 350
367 // Stack parameters/spilled values. 351 // Stack parameters/spilled values.
368 auto p_0 = Define(Slot(-1)); 352 auto p_0 = Define(Slot(-1));
369 auto p_1 = Define(Slot(-2)); 353 auto p_1 = Define(Slot(-2));
370 354
371 // Fill registers. 355 // Fill registers.
372 VReg values[kNumRegs]; 356 VReg values[kNumRegs];
373 for (size_t i = 0; i < arraysize(values); ++i) { 357 for (size_t i = 0; i < arraysize(values); ++i) {
374 values[i] = Define(Reg(static_cast<int>(i))); 358 values[i] = Define(Reg(static_cast<int>(i)));
375 } 359 }
376 360
377 // values[0] will be split in the second half of this instruction. 361 // values[0] will be split in the second half of this instruction.
378 // Models Intel mod instructions. 362 // Models Intel mod instructions.
379 EmitOI(Reg(0), Reg(p_0, 1), UniqueReg(p_1)); 363 EmitOI(Reg(0), Reg(p_0, 1), UniqueReg(p_1));
380 EmitI(Reg(values[0], 0)); 364 EmitI(Reg(values[0], 0));
381 EndBlock(Last()); 365 EndBlock(Last());
382 366
383 Allocate(); 367 Allocate();
384 } 368 }
385 369
386
387 TEST_F(RegisterAllocatorTest, SplitBeforeInstruction2) { 370 TEST_F(RegisterAllocatorTest, SplitBeforeInstruction2) {
388 const int kNumRegs = 6; 371 const int kNumRegs = 6;
389 SetNumRegs(kNumRegs, kNumRegs); 372 SetNumRegs(kNumRegs, kNumRegs);
390 373
391 StartBlock(); 374 StartBlock();
392 375
393 // Stack parameters/spilled values. 376 // Stack parameters/spilled values.
394 auto p_0 = Define(Slot(-1)); 377 auto p_0 = Define(Slot(-1));
395 auto p_1 = Define(Slot(-2)); 378 auto p_1 = Define(Slot(-2));
396 379
397 // Fill registers. 380 // Fill registers.
398 VReg values[kNumRegs]; 381 VReg values[kNumRegs];
399 for (size_t i = 0; i < arraysize(values); ++i) { 382 for (size_t i = 0; i < arraysize(values); ++i) {
400 values[i] = Define(Reg(static_cast<int>(i))); 383 values[i] = Define(Reg(static_cast<int>(i)));
401 } 384 }
402 385
403 // values[0] and [1] will be split in the second half of this instruction. 386 // values[0] and [1] will be split in the second half of this instruction.
404 EmitOOI(Reg(0), Reg(1), Reg(p_0, 0), Reg(p_1, 1)); 387 EmitOOI(Reg(0), Reg(1), Reg(p_0, 0), Reg(p_1, 1));
405 EmitI(Reg(values[0]), Reg(values[1])); 388 EmitI(Reg(values[0]), Reg(values[1]));
406 EndBlock(Last()); 389 EndBlock(Last());
407 390
408 Allocate(); 391 Allocate();
409 } 392 }
410 393
411
412 TEST_F(RegisterAllocatorTest, NestedDiamondPhiMerge) { 394 TEST_F(RegisterAllocatorTest, NestedDiamondPhiMerge) {
413 // Outer diamond. 395 // Outer diamond.
414 StartBlock(); 396 StartBlock();
415 EndBlock(Branch(Imm(), 1, 5)); 397 EndBlock(Branch(Imm(), 1, 5));
416 398
417 // Diamond 1 399 // Diamond 1
418 StartBlock(); 400 StartBlock();
419 EndBlock(Branch(Imm(), 1, 2)); 401 EndBlock(Branch(Imm(), 1, 2));
420 402
421 StartBlock(); 403 StartBlock();
(...skipping 26 matching lines...) Expand all
448 430
449 // Outer diamond merge. 431 // Outer diamond merge.
450 StartBlock(); 432 StartBlock();
451 auto phi = Phi(l_phi, r_phi); 433 auto phi = Phi(l_phi, r_phi);
452 Return(Reg(phi)); 434 Return(Reg(phi));
453 EndBlock(); 435 EndBlock();
454 436
455 Allocate(); 437 Allocate();
456 } 438 }
457 439
458
459 TEST_F(RegisterAllocatorTest, NestedDiamondPhiMergeDifferent) { 440 TEST_F(RegisterAllocatorTest, NestedDiamondPhiMergeDifferent) {
460 // Outer diamond. 441 // Outer diamond.
461 StartBlock(); 442 StartBlock();
462 EndBlock(Branch(Imm(), 1, 5)); 443 EndBlock(Branch(Imm(), 1, 5));
463 444
464 // Diamond 1 445 // Diamond 1
465 StartBlock(); 446 StartBlock();
466 EndBlock(Branch(Imm(), 1, 2)); 447 EndBlock(Branch(Imm(), 1, 2));
467 448
468 StartBlock(); 449 StartBlock();
(...skipping 26 matching lines...) Expand all
495 476
496 // Outer diamond merge. 477 // Outer diamond merge.
497 StartBlock(); 478 StartBlock();
498 auto phi = Phi(l_phi, r_phi); 479 auto phi = Phi(l_phi, r_phi);
499 Return(Reg(phi)); 480 Return(Reg(phi));
500 EndBlock(); 481 EndBlock();
501 482
502 Allocate(); 483 Allocate();
503 } 484 }
504 485
505
506 TEST_F(RegisterAllocatorTest, RegressionSplitBeforeAndMove) { 486 TEST_F(RegisterAllocatorTest, RegressionSplitBeforeAndMove) {
507 StartBlock(); 487 StartBlock();
508 488
509 // Fill registers. 489 // Fill registers.
510 VReg values[kDefaultNRegs]; 490 VReg values[kDefaultNRegs];
511 for (size_t i = 0; i < arraysize(values); ++i) { 491 for (size_t i = 0; i < arraysize(values); ++i) {
512 if (i == 0 || i == 1) continue; // Leave a hole for c_1 to take. 492 if (i == 0 || i == 1) continue; // Leave a hole for c_1 to take.
513 values[i] = Define(Reg(static_cast<int>(i))); 493 values[i] = Define(Reg(static_cast<int>(i)));
514 } 494 }
515 495
516 auto c_0 = DefineConstant(); 496 auto c_0 = DefineConstant();
517 auto c_1 = DefineConstant(); 497 auto c_1 = DefineConstant();
518 498
519 EmitOI(Reg(1), Reg(c_0, 0), UniqueReg(c_1)); 499 EmitOI(Reg(1), Reg(c_0, 0), UniqueReg(c_1));
520 500
521 // Use previous values to force c_1 to split before the previous instruction. 501 // Use previous values to force c_1 to split before the previous instruction.
522 for (size_t i = 0; i < arraysize(values); ++i) { 502 for (size_t i = 0; i < arraysize(values); ++i) {
523 if (i == 0 || i == 1) continue; 503 if (i == 0 || i == 1) continue;
524 EmitI(Reg(values[i], static_cast<int>(i))); 504 EmitI(Reg(values[i], static_cast<int>(i)));
525 } 505 }
526 506
527 EndBlock(Last()); 507 EndBlock(Last());
528 508
529 Allocate(); 509 Allocate();
530 } 510 }
531 511
532
533 TEST_F(RegisterAllocatorTest, RegressionSpillTwice) { 512 TEST_F(RegisterAllocatorTest, RegressionSpillTwice) {
534 StartBlock(); 513 StartBlock();
535 auto p_0 = Parameter(Reg(1)); 514 auto p_0 = Parameter(Reg(1));
536 EmitCall(Slot(-2), Unique(p_0), Reg(p_0, 1)); 515 EmitCall(Slot(-2), Unique(p_0), Reg(p_0, 1));
537 EndBlock(Last()); 516 EndBlock(Last());
538 517
539 Allocate(); 518 Allocate();
540 } 519 }
541 520
542
543 TEST_F(RegisterAllocatorTest, RegressionLoadConstantBeforeSpill) { 521 TEST_F(RegisterAllocatorTest, RegressionLoadConstantBeforeSpill) {
544 StartBlock(); 522 StartBlock();
545 // Fill registers. 523 // Fill registers.
546 VReg values[kDefaultNRegs]; 524 VReg values[kDefaultNRegs];
547 for (size_t i = arraysize(values); i > 0; --i) { 525 for (size_t i = arraysize(values); i > 0; --i) {
548 values[i - 1] = Define(Reg(static_cast<int>(i - 1))); 526 values[i - 1] = Define(Reg(static_cast<int>(i - 1)));
549 } 527 }
550 auto c = DefineConstant(); 528 auto c = DefineConstant();
551 auto to_spill = Define(Reg()); 529 auto to_spill = Define(Reg());
552 EndBlock(Jump(1)); 530 EndBlock(Jump(1));
(...skipping 14 matching lines...) Expand all
567 545
568 StartBlock(); 546 StartBlock();
569 // Force c to split within to_spill's definition. 547 // Force c to split within to_spill's definition.
570 EmitI(Reg(c)); 548 EmitI(Reg(c));
571 EmitI(Reg(to_spill)); 549 EmitI(Reg(to_spill));
572 EndBlock(Last()); 550 EndBlock(Last());
573 551
574 Allocate(); 552 Allocate();
575 } 553 }
576 554
577
578 TEST_F(RegisterAllocatorTest, DiamondWithCallFirstBlock) { 555 TEST_F(RegisterAllocatorTest, DiamondWithCallFirstBlock) {
579 StartBlock(); 556 StartBlock();
580 auto x = EmitOI(Reg(0)); 557 auto x = EmitOI(Reg(0));
581 EndBlock(Branch(Reg(x), 1, 2)); 558 EndBlock(Branch(Reg(x), 1, 2));
582 559
583 StartBlock(); 560 StartBlock();
584 EmitCall(Slot(-1)); 561 EmitCall(Slot(-1));
585 auto occupy = EmitOI(Reg(0)); 562 auto occupy = EmitOI(Reg(0));
586 EndBlock(Jump(2)); 563 EndBlock(Jump(2));
587 564
588 StartBlock(); 565 StartBlock();
589 EndBlock(FallThrough()); 566 EndBlock(FallThrough());
590 567
591 StartBlock(); 568 StartBlock();
592 Use(occupy); 569 Use(occupy);
593 Return(Reg(x)); 570 Return(Reg(x));
594 EndBlock(); 571 EndBlock();
595 Allocate(); 572 Allocate();
596 } 573 }
597 574
598
599 TEST_F(RegisterAllocatorTest, DiamondWithCallSecondBlock) { 575 TEST_F(RegisterAllocatorTest, DiamondWithCallSecondBlock) {
600 StartBlock(); 576 StartBlock();
601 auto x = EmitOI(Reg(0)); 577 auto x = EmitOI(Reg(0));
602 EndBlock(Branch(Reg(x), 1, 2)); 578 EndBlock(Branch(Reg(x), 1, 2));
603 579
604 StartBlock(); 580 StartBlock();
605 EndBlock(Jump(2)); 581 EndBlock(Jump(2));
606 582
607 StartBlock(); 583 StartBlock();
608 EmitCall(Slot(-1)); 584 EmitCall(Slot(-1));
609 auto occupy = EmitOI(Reg(0)); 585 auto occupy = EmitOI(Reg(0));
610 EndBlock(FallThrough()); 586 EndBlock(FallThrough());
611 587
612 StartBlock(); 588 StartBlock();
613 Use(occupy); 589 Use(occupy);
614 Return(Reg(x)); 590 Return(Reg(x));
615 EndBlock(); 591 EndBlock();
616 Allocate(); 592 Allocate();
617 } 593 }
618 594
619
620 TEST_F(RegisterAllocatorTest, SingleDeferredBlockSpill) { 595 TEST_F(RegisterAllocatorTest, SingleDeferredBlockSpill) {
621 StartBlock(); // B0 596 StartBlock(); // B0
622 auto var = EmitOI(Reg(0)); 597 auto var = EmitOI(Reg(0));
623 EndBlock(Branch(Reg(var), 1, 2)); 598 EndBlock(Branch(Reg(var), 1, 2));
624 599
625 StartBlock(); // B1 600 StartBlock(); // B1
626 EndBlock(Jump(2)); 601 EndBlock(Jump(2));
627 602
628 StartBlock(true); // B2 603 StartBlock(true); // B2
629 EmitCall(Slot(-1), Slot(var)); 604 EmitCall(Slot(-1), Slot(var));
(...skipping 18 matching lines...) Expand all
648 623
649 // We should have no parallel moves at the "expect_no_moves" position. 624 // We should have no parallel moves at the "expect_no_moves" position.
650 EXPECT_EQ( 625 EXPECT_EQ(
651 0, GetParallelMoveCount(expect_no_moves, Instruction::START, sequence())); 626 0, GetParallelMoveCount(expect_no_moves, Instruction::START, sequence()));
652 627
653 // The spill should be performed at the position expect_spill_move. 628 // The spill should be performed at the position expect_spill_move.
654 EXPECT_TRUE(IsParallelMovePresent(expect_spill_move, Instruction::START, 629 EXPECT_TRUE(IsParallelMovePresent(expect_spill_move, Instruction::START,
655 sequence(), Reg(0), Slot(0))); 630 sequence(), Reg(0), Slot(0)));
656 } 631 }
657 632
658
659 TEST_F(RegisterAllocatorTest, MultipleDeferredBlockSpills) { 633 TEST_F(RegisterAllocatorTest, MultipleDeferredBlockSpills) {
660 if (!FLAG_turbo_preprocess_ranges) return; 634 if (!FLAG_turbo_preprocess_ranges) return;
661 635
662 StartBlock(); // B0 636 StartBlock(); // B0
663 auto var1 = EmitOI(Reg(0)); 637 auto var1 = EmitOI(Reg(0));
664 auto var2 = EmitOI(Reg(1)); 638 auto var2 = EmitOI(Reg(1));
665 auto var3 = EmitOI(Reg(2)); 639 auto var3 = EmitOI(Reg(2));
666 EndBlock(Branch(Reg(var1, 0), 1, 2)); 640 EndBlock(Branch(Reg(var1, 0), 1, 2));
667 641
668 StartBlock(true); // B1 642 StartBlock(true); // B1
(...skipping 30 matching lines...) Expand all
699 EXPECT_TRUE(IsParallelMovePresent(call_in_b1, Instruction::START, sequence(), 673 EXPECT_TRUE(IsParallelMovePresent(call_in_b1, Instruction::START, sequence(),
700 Reg(var3_reg), Slot(var3_slot))); 674 Reg(var3_reg), Slot(var3_slot)));
701 EXPECT_TRUE(IsParallelMovePresent(end_of_b1, Instruction::START, sequence(), 675 EXPECT_TRUE(IsParallelMovePresent(end_of_b1, Instruction::START, sequence(),
702 Slot(var3_slot), Reg())); 676 Slot(var3_slot), Reg()));
703 677
704 EXPECT_TRUE(IsParallelMovePresent(call_in_b2, Instruction::START, sequence(), 678 EXPECT_TRUE(IsParallelMovePresent(call_in_b2, Instruction::START, sequence(),
705 Reg(var3_reg), Slot(var3_slot))); 679 Reg(var3_reg), Slot(var3_slot)));
706 EXPECT_TRUE(IsParallelMovePresent(end_of_b2, Instruction::START, sequence(), 680 EXPECT_TRUE(IsParallelMovePresent(end_of_b2, Instruction::START, sequence(),
707 Slot(var3_slot), Reg())); 681 Slot(var3_slot), Reg()));
708 682
709
710 EXPECT_EQ(0, 683 EXPECT_EQ(0,
711 GetParallelMoveCount(start_of_b3, Instruction::START, sequence())); 684 GetParallelMoveCount(start_of_b3, Instruction::START, sequence()));
712 } 685 }
713 686
714
715 namespace { 687 namespace {
716 688
717 enum class ParameterType { kFixedSlot, kSlot, kRegister, kFixedRegister }; 689 enum class ParameterType { kFixedSlot, kSlot, kRegister, kFixedRegister };
718 690
719 const ParameterType kParameterTypes[] = { 691 const ParameterType kParameterTypes[] = {
720 ParameterType::kFixedSlot, ParameterType::kSlot, ParameterType::kRegister, 692 ParameterType::kFixedSlot, ParameterType::kSlot, ParameterType::kRegister,
721 ParameterType::kFixedRegister}; 693 ParameterType::kFixedRegister};
722 694
723 class SlotConstraintTest : public RegisterAllocatorTest, 695 class SlotConstraintTest : public RegisterAllocatorTest,
724 public ::testing::WithParamInterface< 696 public ::testing::WithParamInterface<
725 ::testing::tuple<ParameterType, int>> { 697 ::testing::tuple<ParameterType, int>> {
726 public: 698 public:
727 static const int kMaxVariant = 5; 699 static const int kMaxVariant = 5;
728 700
729 protected: 701 protected:
730 ParameterType parameter_type() const { 702 ParameterType parameter_type() const {
731 return ::testing::get<0>(B::GetParam()); 703 return ::testing::get<0>(B::GetParam());
732 } 704 }
733 int variant() const { return ::testing::get<1>(B::GetParam()); } 705 int variant() const { return ::testing::get<1>(B::GetParam()); }
734 706
735 private: 707 private:
736 typedef ::testing::WithParamInterface<::testing::tuple<ParameterType, int>> B; 708 typedef ::testing::WithParamInterface<::testing::tuple<ParameterType, int>> B;
737 }; 709 };
738 710
739 } // namespace 711 } // namespace
740 712
741
742 #if GTEST_HAS_COMBINE 713 #if GTEST_HAS_COMBINE
743 714
744 TEST_P(SlotConstraintTest, SlotConstraint) { 715 TEST_P(SlotConstraintTest, SlotConstraint) {
745 StartBlock(); 716 StartBlock();
746 VReg p_0; 717 VReg p_0;
747 switch (parameter_type()) { 718 switch (parameter_type()) {
748 case ParameterType::kFixedSlot: 719 case ParameterType::kFixedSlot:
749 p_0 = Parameter(Slot(-1)); 720 p_0 = Parameter(Slot(-1));
750 break; 721 break;
751 case ParameterType::kSlot: 722 case ParameterType::kSlot:
(...skipping 26 matching lines...) Expand all
778 break; 749 break;
779 default: 750 default:
780 UNREACHABLE(); 751 UNREACHABLE();
781 break; 752 break;
782 } 753 }
783 EndBlock(Last()); 754 EndBlock(Last());
784 755
785 Allocate(); 756 Allocate();
786 } 757 }
787 758
788
789 INSTANTIATE_TEST_CASE_P( 759 INSTANTIATE_TEST_CASE_P(
790 RegisterAllocatorTest, SlotConstraintTest, 760 RegisterAllocatorTest, SlotConstraintTest,
791 ::testing::Combine(::testing::ValuesIn(kParameterTypes), 761 ::testing::Combine(::testing::ValuesIn(kParameterTypes),
792 ::testing::Range(0, SlotConstraintTest::kMaxVariant))); 762 ::testing::Range(0, SlotConstraintTest::kMaxVariant)));
793 763
794 #endif // GTEST_HAS_COMBINE 764 #endif // GTEST_HAS_COMBINE
795 765
796 } // namespace compiler 766 } // namespace compiler
797 } // namespace internal 767 } // namespace internal
798 } // namespace v8 768 } // namespace v8
OLDNEW
« no previous file with comments | « test/unittests/compiler/regalloc/move-optimizer-unittest.cc ('k') | test/unittests/compiler/register-allocator-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698