LCOV - code coverage report
Current view: top level - test/unittests/compiler/backend - instruction-sequence-unittest.h (source / functions) Hit Total Coverage
Test: app.info Lines: 24 24 100.0 %
Date: 2019-03-21 Functions: 4 5 80.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             : #ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_
       6             : #define V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_
       7             : 
       8             : #include <memory>
       9             : 
      10             : #include "src/compiler/backend/instruction.h"
      11             : #include "src/register-configuration.h"
      12             : #include "test/unittests/test-utils.h"
      13             : #include "testing/gmock/include/gmock/gmock.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : namespace compiler {
      18             : 
      19         104 : class InstructionSequenceTest : public TestWithIsolateAndZone {
      20             :  public:
      21             :   static constexpr int kNoValue = kMinInt;
      22             :   static constexpr MachineRepresentation kNoRep = MachineRepresentation::kNone;
      23             :   static constexpr MachineRepresentation kFloat32 =
      24             :       MachineRepresentation::kFloat32;
      25             :   static constexpr MachineRepresentation kFloat64 =
      26             :       MachineRepresentation::kFloat64;
      27             :   static constexpr MachineRepresentation kSimd128 =
      28             :       MachineRepresentation::kSimd128;
      29             : 
      30             :   typedef RpoNumber Rpo;
      31             : 
      32             :   struct VReg {
      33         785 :     VReg() : value_(kNoValue) {}
      34           2 :     VReg(PhiInstruction* phi) : value_(phi->virtual_register()) {}  // NOLINT
      35             :     explicit VReg(int value, MachineRepresentation rep = kNoRep)
      36             :         : value_(value), rep_(rep) {}
      37             :     int value_;
      38             :     MachineRepresentation rep_ = kNoRep;
      39             :   };
      40             : 
      41             :   typedef std::pair<VReg, VReg> VRegPair;
      42             : 
      43             :   enum TestOperandType {
      44             :     kInvalid,
      45             :     kSameAsFirst,
      46             :     kRegister,
      47             :     kFixedRegister,
      48             :     kSlot,
      49             :     kFixedSlot,
      50             :     kExplicit,
      51             :     kImmediate,
      52             :     kNone,
      53             :     kConstant,
      54             :     kUnique,
      55             :     kUniqueRegister
      56             :   };
      57             : 
      58             :   struct TestOperand {
      59         552 :     TestOperand() : type_(kInvalid), vreg_(), value_(kNoValue), rep_(kNoRep) {}
      60             :     explicit TestOperand(TestOperandType type)
      61          10 :         : type_(type), vreg_(), value_(kNoValue), rep_(kNoRep) {}
      62             :     // For tests that do register allocation.
      63             :     TestOperand(TestOperandType type, VReg vreg, int value = kNoValue)
      64         257 :         : type_(type), vreg_(vreg), value_(value), rep_(vreg.rep_) {}
      65             :     // For immediates, constants, and tests that don't do register allocation.
      66             :     TestOperand(TestOperandType type, int value,
      67             :                 MachineRepresentation rep = kNoRep)
      68         282 :         : type_(type), vreg_(), value_(value), rep_(rep) {}
      69             : 
      70             :     TestOperandType type_;
      71             :     VReg vreg_;
      72             :     int value_;
      73             :     MachineRepresentation rep_;
      74             :   };
      75             : 
      76             :   static TestOperand Same() { return TestOperand(kSameAsFirst); }
      77             : 
      78             :   static TestOperand ExplicitReg(int index) {
      79             :     TestOperandType type = kExplicit;
      80             :     return TestOperand(type, index);
      81             :   }
      82             : 
      83             :   static TestOperand ExplicitFPReg(int index,
      84             :                                    MachineRepresentation rep = kFloat64) {
      85             :     TestOperandType type = kExplicit;
      86             :     return TestOperand(type, index, rep);
      87             :   }
      88             : 
      89             :   static TestOperand Reg(VReg vreg, int index = kNoValue) {
      90          88 :     TestOperandType type = (index == kNoValue) ? kRegister : kFixedRegister;
      91             :     return TestOperand(type, vreg, index);
      92             :   }
      93             : 
      94             :   static TestOperand Reg(int index = kNoValue,
      95             :                          MachineRepresentation rep = kNoRep) {
      96             :     return Reg(VReg(kNoValue, rep), index);
      97             :   }
      98             : 
      99             :   static TestOperand FPReg(int index = kNoValue,
     100             :                            MachineRepresentation rep = kFloat64) {
     101             :     return Reg(index, rep);
     102             :   }
     103             : 
     104             :   static TestOperand Slot(VReg vreg, int index = kNoValue) {
     105          48 :     TestOperandType type = (index == kNoValue) ? kSlot : kFixedSlot;
     106             :     return TestOperand(type, vreg, index);
     107             :   }
     108             : 
     109             :   static TestOperand Slot(int index = kNoValue,
     110             :                           MachineRepresentation rep = kNoRep) {
     111             :     return Slot(VReg(kNoValue, rep), index);
     112             :   }
     113             : 
     114             :   static TestOperand Const(int index) {
     115             :     CHECK_NE(kNoValue, index);
     116             :     return TestOperand(kConstant, index);
     117             :   }
     118             : 
     119             :   static TestOperand Use(VReg vreg) { return TestOperand(kNone, vreg); }
     120             : 
     121             :   static TestOperand Use() { return Use(VReg()); }
     122             : 
     123             :   static TestOperand Unique(VReg vreg) { return TestOperand(kUnique, vreg); }
     124             : 
     125             :   static TestOperand UniqueReg(VReg vreg) {
     126             :     return TestOperand(kUniqueRegister, vreg);
     127             :   }
     128             : 
     129             :   enum BlockCompletionType { kBlockEnd, kFallThrough, kBranch, kJump };
     130             : 
     131             :   struct BlockCompletion {
     132             :     BlockCompletionType type_;
     133             :     TestOperand op_;
     134             :     int offset_0_;
     135             :     int offset_1_;
     136             :   };
     137             : 
     138             :   static BlockCompletion FallThrough() {
     139          29 :     BlockCompletion completion = {kFallThrough, TestOperand(), 1, kNoValue};
     140             :     return completion;
     141             :   }
     142             : 
     143             :   static BlockCompletion Jump(int offset) {
     144          65 :     BlockCompletion completion = {kJump, TestOperand(), offset, kNoValue};
     145             :     return completion;
     146             :   }
     147             : 
     148             :   static BlockCompletion Branch(TestOperand op, int left_offset,
     149             :                                 int right_offset) {
     150          22 :     BlockCompletion completion = {kBranch, op, left_offset, right_offset};
     151             :     return completion;
     152             :   }
     153             : 
     154             :   static BlockCompletion Last() {
     155          38 :     BlockCompletion completion = {kBlockEnd, TestOperand(), kNoValue, kNoValue};
     156             :     return completion;
     157             :   }
     158             : 
     159             :   InstructionSequenceTest();
     160             : 
     161             :   void SetNumRegs(int num_general_registers, int num_double_registers);
     162             :   int GetNumRegs(MachineRepresentation rep);
     163             :   int GetAllocatableCode(int index, MachineRepresentation rep = kNoRep);
     164             :   const RegisterConfiguration* config();
     165             :   InstructionSequence* sequence();
     166             : 
     167             :   void StartLoop(int loop_blocks);
     168             :   void EndLoop();
     169             :   void StartBlock(bool deferred = false);
     170             :   Instruction* EndBlock(BlockCompletion completion = FallThrough());
     171             : 
     172             :   TestOperand Imm(int32_t imm = 0);
     173             :   VReg Define(TestOperand output_op);
     174          61 :   VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); }
     175           6 :   VReg FPParameter(MachineRepresentation rep = kFloat64) {
     176           6 :     return Parameter(FPReg(kNoValue, rep));
     177             :   }
     178             : 
     179             :   MachineRepresentation GetCanonicalRep(TestOperand op) {
     180             :     return IsFloatingPoint(op.rep_) ? op.rep_
     181         290 :                                     : sequence()->DefaultRepresentation();
     182             :   }
     183             : 
     184             :   Instruction* Return(TestOperand input_op_0);
     185           8 :   Instruction* Return(VReg vreg) { return Return(Reg(vreg, 0)); }
     186             : 
     187             :   PhiInstruction* Phi(VReg incoming_vreg_0 = VReg(),
     188             :                       VReg incoming_vreg_1 = VReg(),
     189             :                       VReg incoming_vreg_2 = VReg(),
     190             :                       VReg incoming_vreg_3 = VReg());
     191             :   PhiInstruction* Phi(VReg incoming_vreg_0, size_t input_count);
     192             :   void SetInput(PhiInstruction* phi, size_t input, VReg vreg);
     193             : 
     194             :   VReg DefineConstant(int32_t imm = 0);
     195             :   Instruction* EmitNop();
     196             :   Instruction* EmitI(size_t input_size, TestOperand* inputs);
     197             :   Instruction* EmitI(TestOperand input_op_0 = TestOperand(),
     198             :                      TestOperand input_op_1 = TestOperand(),
     199             :                      TestOperand input_op_2 = TestOperand(),
     200             :                      TestOperand input_op_3 = TestOperand());
     201             :   VReg EmitOI(TestOperand output_op, size_t input_size, TestOperand* inputs);
     202             :   VReg EmitOI(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
     203             :               TestOperand input_op_1 = TestOperand(),
     204             :               TestOperand input_op_2 = TestOperand(),
     205             :               TestOperand input_op_3 = TestOperand());
     206             :   VRegPair EmitOOI(TestOperand output_op_0, TestOperand output_op_1,
     207             :                    size_t input_size, TestOperand* inputs);
     208             :   VRegPair EmitOOI(TestOperand output_op_0, TestOperand output_op_1,
     209             :                    TestOperand input_op_0 = TestOperand(),
     210             :                    TestOperand input_op_1 = TestOperand(),
     211             :                    TestOperand input_op_2 = TestOperand(),
     212             :                    TestOperand input_op_3 = TestOperand());
     213             :   VReg EmitCall(TestOperand output_op, size_t input_size, TestOperand* inputs);
     214             :   VReg EmitCall(TestOperand output_op, TestOperand input_op_0 = TestOperand(),
     215             :                 TestOperand input_op_1 = TestOperand(),
     216             :                 TestOperand input_op_2 = TestOperand(),
     217             :                 TestOperand input_op_3 = TestOperand());
     218             : 
     219             :   InstructionBlock* current_block() const { return current_block_; }
     220             : 
     221             :   // Called after all instructions have been inserted.
     222             :   void WireBlocks();
     223             : 
     224             :  private:
     225         197 :   virtual bool DoesRegisterAllocation() const { return true; }
     226             : 
     227         346 :   VReg NewReg(TestOperand op = TestOperand()) {
     228         346 :     int vreg = sequence()->NextVirtualRegister();
     229         346 :     if (IsFloatingPoint(op.rep_))
     230           8 :       sequence()->MarkAsRepresentation(op.rep_, vreg);
     231         346 :     return VReg(vreg, op.rep_);
     232             :   }
     233             : 
     234             :   static TestOperand Invalid() { return TestOperand(kInvalid); }
     235             : 
     236             :   Instruction* EmitBranch(TestOperand input_op);
     237             :   Instruction* EmitFallThrough();
     238             :   Instruction* EmitJump();
     239             :   Instruction* NewInstruction(InstructionCode code, size_t outputs_size,
     240             :                               InstructionOperand* outputs,
     241             :                               size_t inputs_size = 0,
     242             :                               InstructionOperand* inputs = nullptr,
     243             :                               size_t temps_size = 0,
     244             :                               InstructionOperand* temps = nullptr);
     245             :   InstructionOperand Unallocated(TestOperand op,
     246             :                                  UnallocatedOperand::ExtendedPolicy policy);
     247             :   InstructionOperand Unallocated(TestOperand op,
     248             :                                  UnallocatedOperand::ExtendedPolicy policy,
     249             :                                  UnallocatedOperand::Lifetime lifetime);
     250             :   InstructionOperand Unallocated(TestOperand op,
     251             :                                  UnallocatedOperand::ExtendedPolicy policy,
     252             :                                  int index);
     253             :   InstructionOperand Unallocated(TestOperand op,
     254             :                                  UnallocatedOperand::BasicPolicy policy,
     255             :                                  int index);
     256             :   InstructionOperand* ConvertInputs(size_t input_size, TestOperand* inputs);
     257             :   InstructionOperand ConvertInputOp(TestOperand op);
     258             :   InstructionOperand ConvertOutputOp(VReg vreg, TestOperand op);
     259             :   InstructionBlock* NewBlock(bool deferred = false);
     260             :   void WireBlock(size_t block_offset, int jump_offset);
     261             : 
     262             :   Instruction* Emit(InstructionCode code, size_t outputs_size = 0,
     263             :                     InstructionOperand* outputs = nullptr,
     264             :                     size_t inputs_size = 0,
     265             :                     InstructionOperand* inputs = nullptr, size_t temps_size = 0,
     266             :                     InstructionOperand* temps = nullptr, bool is_call = false);
     267             : 
     268             :   Instruction* AddInstruction(Instruction* instruction);
     269             : 
     270             :   struct LoopData {
     271             :     Rpo loop_header_;
     272             :     int expected_blocks_;
     273             :   };
     274             : 
     275             :   typedef std::vector<LoopData> LoopBlocks;
     276             :   typedef std::map<int, const Instruction*> Instructions;
     277             :   typedef std::vector<BlockCompletion> Completions;
     278             : 
     279             :   std::unique_ptr<RegisterConfiguration> config_;
     280             :   InstructionSequence* sequence_;
     281             :   int num_general_registers_;
     282             :   int num_double_registers_;
     283             : 
     284             :   // Block building state.
     285             :   InstructionBlocks instruction_blocks_;
     286             :   Instructions instructions_;
     287             :   Completions completions_;
     288             :   LoopBlocks loop_blocks_;
     289             :   InstructionBlock* current_block_;
     290             :   bool block_returns_;
     291             : 
     292             :   DISALLOW_COPY_AND_ASSIGN(InstructionSequenceTest);
     293             : };
     294             : 
     295             : }  // namespace compiler
     296             : }  // namespace internal
     297             : }  // namespace v8
     298             : 
     299             : #endif  // V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_

Generated by: LCOV version 1.10