LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-instruction.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 168 168 100.0 %
Date: 2017-10-20 Functions: 13 13 100.0 %

          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/code-generator.h"
       6             : #include "src/compiler/common-operator.h"
       7             : #include "src/compiler/graph.h"
       8             : #include "src/compiler/instruction.h"
       9             : #include "src/compiler/linkage.h"
      10             : #include "src/compiler/machine-operator.h"
      11             : #include "src/compiler/node.h"
      12             : #include "src/compiler/operator.h"
      13             : #include "src/compiler/schedule.h"
      14             : #include "src/compiler/scheduler.h"
      15             : #include "src/objects-inl.h"
      16             : #include "test/cctest/cctest.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace compiler {
      21             : 
      22             : typedef v8::internal::compiler::Instruction TestInstr;
      23             : typedef v8::internal::compiler::InstructionSequence TestInstrSeq;
      24             : 
      25             : // A testing helper for the register code abstraction.
      26          30 : class InstructionTester : public HandleAndZoneScope {
      27             :  public:  // We're all friends here.
      28          30 :   InstructionTester()
      29             :       : graph(zone()),
      30             :         schedule(zone()),
      31             :         common(zone()),
      32             :         machine(zone()),
      33         150 :         code(nullptr) {}
      34             : 
      35             :   Graph graph;
      36             :   Schedule schedule;
      37             :   CommonOperatorBuilder common;
      38             :   MachineOperatorBuilder machine;
      39             :   TestInstrSeq* code;
      40             : 
      41             :   Zone* zone() { return main_zone(); }
      42             : 
      43          30 :   void allocCode() {
      44          60 :     if (schedule.rpo_order()->size() == 0) {
      45             :       // Compute the RPO order.
      46          60 :       Scheduler::ComputeSpecialRPO(main_zone(), &schedule);
      47          60 :       CHECK_NE(0u, schedule.rpo_order()->size());
      48             :     }
      49             :     InstructionBlocks* instruction_blocks =
      50          60 :         TestInstrSeq::InstructionBlocksFor(main_zone(), &schedule);
      51             :     code = new (main_zone())
      52          60 :         TestInstrSeq(main_isolate(), main_zone(), instruction_blocks);
      53          30 :   }
      54             : 
      55          78 :   Node* Int32Constant(int32_t val) {
      56          78 :     Node* node = graph.NewNode(common.Int32Constant(val));
      57          78 :     schedule.AddNode(schedule.start(), node);
      58          78 :     return node;
      59             :   }
      60             : 
      61             :   Node* Float64Constant(double val) {
      62             :     Node* node = graph.NewNode(common.Float64Constant(val));
      63             :     schedule.AddNode(schedule.start(), node);
      64             :     return node;
      65             :   }
      66             : 
      67             :   Node* Parameter(int32_t which) {
      68             :     Node* node = graph.NewNode(common.Parameter(which));
      69             :     schedule.AddNode(schedule.start(), node);
      70             :     return node;
      71             :   }
      72             : 
      73             :   Node* NewNode(BasicBlock* block) {
      74             :     Node* node = graph.NewNode(common.Int32Constant(111));
      75             :     schedule.AddNode(block, node);
      76             :     return node;
      77             :   }
      78             : 
      79          54 :   int NewInstr() {
      80             :     InstructionCode opcode = static_cast<InstructionCode>(110);
      81          54 :     TestInstr* instr = TestInstr::New(zone(), opcode);
      82          54 :     return code->AddInstruction(instr);
      83             :   }
      84             : 
      85             :   UnallocatedOperand Unallocated(int vreg) {
      86             :     return UnallocatedOperand(UnallocatedOperand::ANY, vreg);
      87             :   }
      88             : 
      89         180 :   RpoNumber RpoFor(BasicBlock* block) {
      90             :     return RpoNumber::FromInt(block->rpo_number());
      91             :   }
      92             : 
      93             :   InstructionBlock* BlockAt(BasicBlock* block) {
      94          84 :     return code->InstructionBlockAt(RpoFor(block));
      95             :   }
      96         102 :   BasicBlock* GetBasicBlock(int instruction_index) {
      97             :     const InstructionBlock* block =
      98         102 :         code->GetInstructionBlock(instruction_index);
      99         102 :     return schedule.rpo_order()->at(block->rpo_number().ToSize());
     100             :   }
     101          24 :   int first_instruction_index(BasicBlock* block) {
     102          24 :     return BlockAt(block)->first_instruction_index();
     103             :   }
     104          24 :   int last_instruction_index(BasicBlock* block) {
     105          24 :     return BlockAt(block)->last_instruction_index();
     106             :   }
     107             : };
     108             : 
     109             : 
     110       23724 : TEST(InstructionBasic) {
     111           6 :   InstructionTester R;
     112             : 
     113          66 :   for (int i = 0; i < 10; i++) {
     114          60 :     R.Int32Constant(i);  // Add some nodes to the graph.
     115             :   }
     116             : 
     117           6 :   BasicBlock* last = R.schedule.start();
     118          36 :   for (int i = 0; i < 5; i++) {
     119          30 :     BasicBlock* block = R.schedule.NewBasicBlock();
     120          30 :     R.schedule.AddGoto(last, block);
     121             :     last = block;
     122             :   }
     123             : 
     124           6 :   R.allocCode();
     125             : 
     126             :   BasicBlockVector* blocks = R.schedule.rpo_order();
     127          18 :   CHECK_EQ(static_cast<int>(blocks->size()), R.code->InstructionBlockCount());
     128             : 
     129         114 :   for (auto block : *blocks) {
     130          36 :     CHECK_EQ(block->rpo_number(), R.BlockAt(block)->rpo_number().ToInt());
     131          36 :     CHECK(!block->loop_end());
     132             :   }
     133           6 : }
     134             : 
     135             : 
     136       23724 : TEST(InstructionGetBasicBlock) {
     137           6 :   InstructionTester R;
     138             : 
     139           6 :   BasicBlock* b0 = R.schedule.start();
     140           6 :   BasicBlock* b1 = R.schedule.NewBasicBlock();
     141           6 :   BasicBlock* b2 = R.schedule.NewBasicBlock();
     142           6 :   BasicBlock* b3 = R.schedule.end();
     143             : 
     144           6 :   R.schedule.AddGoto(b0, b1);
     145           6 :   R.schedule.AddGoto(b1, b2);
     146           6 :   R.schedule.AddGoto(b2, b3);
     147             : 
     148           6 :   R.allocCode();
     149             : 
     150           6 :   R.code->StartBlock(R.RpoFor(b0));
     151           6 :   int i0 = R.NewInstr();
     152           6 :   int i1 = R.NewInstr();
     153           6 :   R.code->EndBlock(R.RpoFor(b0));
     154           6 :   R.code->StartBlock(R.RpoFor(b1));
     155           6 :   int i2 = R.NewInstr();
     156           6 :   int i3 = R.NewInstr();
     157           6 :   int i4 = R.NewInstr();
     158           6 :   int i5 = R.NewInstr();
     159           6 :   R.code->EndBlock(R.RpoFor(b1));
     160           6 :   R.code->StartBlock(R.RpoFor(b2));
     161           6 :   int i6 = R.NewInstr();
     162           6 :   int i7 = R.NewInstr();
     163           6 :   int i8 = R.NewInstr();
     164           6 :   R.code->EndBlock(R.RpoFor(b2));
     165           6 :   R.code->StartBlock(R.RpoFor(b3));
     166           6 :   R.code->EndBlock(R.RpoFor(b3));
     167             : 
     168           6 :   CHECK_EQ(b0, R.GetBasicBlock(i0));
     169           6 :   CHECK_EQ(b0, R.GetBasicBlock(i1));
     170             : 
     171           6 :   CHECK_EQ(b1, R.GetBasicBlock(i2));
     172           6 :   CHECK_EQ(b1, R.GetBasicBlock(i3));
     173           6 :   CHECK_EQ(b1, R.GetBasicBlock(i4));
     174           6 :   CHECK_EQ(b1, R.GetBasicBlock(i5));
     175             : 
     176           6 :   CHECK_EQ(b2, R.GetBasicBlock(i6));
     177           6 :   CHECK_EQ(b2, R.GetBasicBlock(i7));
     178           6 :   CHECK_EQ(b2, R.GetBasicBlock(i8));
     179             : 
     180           6 :   CHECK_EQ(b0, R.GetBasicBlock(R.first_instruction_index(b0)));
     181           6 :   CHECK_EQ(b0, R.GetBasicBlock(R.last_instruction_index(b0)));
     182             : 
     183           6 :   CHECK_EQ(b1, R.GetBasicBlock(R.first_instruction_index(b1)));
     184           6 :   CHECK_EQ(b1, R.GetBasicBlock(R.last_instruction_index(b1)));
     185             : 
     186           6 :   CHECK_EQ(b2, R.GetBasicBlock(R.first_instruction_index(b2)));
     187           6 :   CHECK_EQ(b2, R.GetBasicBlock(R.last_instruction_index(b2)));
     188             : 
     189           6 :   CHECK_EQ(b3, R.GetBasicBlock(R.first_instruction_index(b3)));
     190           6 :   CHECK_EQ(b3, R.GetBasicBlock(R.last_instruction_index(b3)));
     191           6 : }
     192             : 
     193             : 
     194       23724 : TEST(InstructionIsGapAt) {
     195           6 :   InstructionTester R;
     196             : 
     197           6 :   BasicBlock* b0 = R.schedule.start();
     198           6 :   R.schedule.AddReturn(b0, R.Int32Constant(1));
     199             : 
     200           6 :   R.allocCode();
     201           6 :   TestInstr* i0 = TestInstr::New(R.zone(), 100);
     202           6 :   TestInstr* g = TestInstr::New(R.zone(), 103);
     203           6 :   R.code->StartBlock(R.RpoFor(b0));
     204           6 :   R.code->AddInstruction(i0);
     205           6 :   R.code->AddInstruction(g);
     206           6 :   R.code->EndBlock(R.RpoFor(b0));
     207             : 
     208          12 :   CHECK_EQ(2, R.code->instructions().size());
     209           6 : }
     210             : 
     211             : 
     212       23724 : TEST(InstructionIsGapAt2) {
     213           6 :   InstructionTester R;
     214             : 
     215           6 :   BasicBlock* b0 = R.schedule.start();
     216           6 :   BasicBlock* b1 = R.schedule.end();
     217           6 :   R.schedule.AddGoto(b0, b1);
     218           6 :   R.schedule.AddReturn(b1, R.Int32Constant(1));
     219             : 
     220           6 :   R.allocCode();
     221           6 :   TestInstr* i0 = TestInstr::New(R.zone(), 100);
     222           6 :   TestInstr* g = TestInstr::New(R.zone(), 103);
     223           6 :   R.code->StartBlock(R.RpoFor(b0));
     224           6 :   R.code->AddInstruction(i0);
     225           6 :   R.code->AddInstruction(g);
     226           6 :   R.code->EndBlock(R.RpoFor(b0));
     227             : 
     228           6 :   TestInstr* i1 = TestInstr::New(R.zone(), 102);
     229           6 :   TestInstr* g1 = TestInstr::New(R.zone(), 104);
     230           6 :   R.code->StartBlock(R.RpoFor(b1));
     231           6 :   R.code->AddInstruction(i1);
     232           6 :   R.code->AddInstruction(g1);
     233           6 :   R.code->EndBlock(R.RpoFor(b1));
     234             : 
     235          12 :   CHECK_EQ(4, R.code->instructions().size());
     236           6 : }
     237             : 
     238             : 
     239       23724 : TEST(InstructionAddGapMove) {
     240           6 :   InstructionTester R;
     241             : 
     242           6 :   BasicBlock* b0 = R.schedule.start();
     243           6 :   R.schedule.AddReturn(b0, R.Int32Constant(1));
     244             : 
     245           6 :   R.allocCode();
     246           6 :   TestInstr* i0 = TestInstr::New(R.zone(), 100);
     247           6 :   TestInstr* g = TestInstr::New(R.zone(), 103);
     248           6 :   R.code->StartBlock(R.RpoFor(b0));
     249           6 :   R.code->AddInstruction(i0);
     250           6 :   R.code->AddInstruction(g);
     251           6 :   R.code->EndBlock(R.RpoFor(b0));
     252             : 
     253          12 :   CHECK_EQ(2, R.code->instructions().size());
     254             : 
     255             :   int index = 0;
     256          30 :   for (auto instr : R.code->instructions()) {
     257          24 :     UnallocatedOperand op1 = R.Unallocated(index++);
     258          24 :     UnallocatedOperand op2 = R.Unallocated(index++);
     259             :     instr->GetOrCreateParallelMove(TestInstr::START, R.zone())
     260          12 :         ->AddMove(op1, op2);
     261             :     ParallelMove* move = instr->GetParallelMove(TestInstr::START);
     262          12 :     CHECK(move);
     263          24 :     CHECK_EQ(1u, move->size());
     264          12 :     MoveOperands* cur = move->at(0);
     265          12 :     CHECK(op1.Equals(cur->source()));
     266          12 :     CHECK(op2.Equals(cur->destination()));
     267             :   }
     268           6 : }
     269             : 
     270             : 
     271       23724 : TEST(InstructionOperands) {
     272           6 :   v8::internal::AccountingAllocator allocator;
     273          12 :   Zone zone(&allocator, ZONE_NAME);
     274             : 
     275             :   {
     276           6 :     TestInstr* i = TestInstr::New(&zone, 101);
     277           6 :     CHECK_EQ(0, static_cast<int>(i->OutputCount()));
     278           6 :     CHECK_EQ(0, static_cast<int>(i->InputCount()));
     279           6 :     CHECK_EQ(0, static_cast<int>(i->TempCount()));
     280             :   }
     281             : 
     282             :   int vreg = 15;
     283             :   InstructionOperand outputs[] = {
     284             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     285             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     286             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     287           6 :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
     288             : 
     289             :   InstructionOperand inputs[] = {
     290             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     291             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     292             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     293           6 :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
     294             : 
     295             :   InstructionOperand temps[] = {
     296             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     297             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     298             :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
     299           6 :       UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
     300             : 
     301          30 :   for (size_t i = 0; i < arraysize(outputs); i++) {
     302          96 :     for (size_t j = 0; j < arraysize(inputs); j++) {
     303         384 :       for (size_t k = 0; k < arraysize(temps); k++) {
     304         384 :         TestInstr* m =
     305         384 :             TestInstr::New(&zone, 101, i, outputs, j, inputs, k, temps);
     306         384 :         CHECK(i == m->OutputCount());
     307         384 :         CHECK(j == m->InputCount());
     308         384 :         CHECK(k == m->TempCount());
     309             : 
     310         576 :         for (size_t z = 0; z < i; z++) {
     311        1152 :           CHECK(outputs[z].Equals(*m->OutputAt(z)));
     312             :         }
     313             : 
     314         576 :         for (size_t z = 0; z < j; z++) {
     315        1152 :           CHECK(inputs[z].Equals(*m->InputAt(z)));
     316             :         }
     317             : 
     318         576 :         for (size_t z = 0; z < k; z++) {
     319        1152 :           CHECK(temps[z].Equals(*m->TempAt(z)));
     320             :         }
     321             :       }
     322             :     }
     323           6 :   }
     324           6 : }
     325             : 
     326             : }  // namespace compiler
     327             : }  // namespace internal
     328       71154 : }  // namespace v8

Generated by: LCOV version 1.10