| OLD | NEW |
| 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 #ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_ | 5 #ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_ |
| 6 #define V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_ | 6 #define V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_ |
| 7 | 7 |
| 8 #include <memory> | 8 #include <memory> |
| 9 | 9 |
| 10 #include "src/compiler/instruction.h" | 10 #include "src/compiler/instruction.h" |
| 11 #include "test/unittests/test-utils.h" | 11 #include "test/unittests/test-utils.h" |
| 12 #include "testing/gmock/include/gmock/gmock.h" | 12 #include "testing/gmock/include/gmock/gmock.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 namespace compiler { | 16 namespace compiler { |
| 17 | 17 |
| 18 class InstructionSequenceTest : public TestWithIsolateAndZone { | 18 class InstructionSequenceTest : public TestWithIsolateAndZone { |
| 19 public: | 19 public: |
| 20 static const int kDefaultNRegs = 8; | 20 static const int kDefaultNRegs = 8; |
| 21 static const int kNoValue = kMinInt; | 21 static const int kNoValue = kMinInt; |
| 22 static const MachineRepresentation kNoRep = MachineRepresentation::kNone; |
| 23 static const MachineRepresentation kFloat64 = MachineRepresentation::kFloat64; |
| 22 | 24 |
| 23 typedef RpoNumber Rpo; | 25 typedef RpoNumber Rpo; |
| 24 | 26 |
| 25 struct VReg { | 27 struct VReg { |
| 26 VReg() : value_(kNoValue) {} | 28 VReg() : value_(kNoValue) {} |
| 27 VReg(PhiInstruction* phi) : value_(phi->virtual_register()) {} // NOLINT | 29 VReg(PhiInstruction* phi) : value_(phi->virtual_register()) {} // NOLINT |
| 28 explicit VReg(int value) : value_(value) {} | 30 explicit VReg(int value, MachineRepresentation rep = kNoRep) |
| 31 : value_(value), rep_(rep) {} |
| 29 int value_; | 32 int value_; |
| 33 MachineRepresentation rep_ = kNoRep; |
| 30 }; | 34 }; |
| 31 | 35 |
| 32 typedef std::pair<VReg, VReg> VRegPair; | 36 typedef std::pair<VReg, VReg> VRegPair; |
| 33 | 37 |
| 34 enum TestOperandType { | 38 enum TestOperandType { |
| 35 kInvalid, | 39 kInvalid, |
| 36 kSameAsFirst, | 40 kSameAsFirst, |
| 37 kRegister, | 41 kRegister, |
| 38 kFixedRegister, | 42 kFixedRegister, |
| 39 kSlot, | 43 kSlot, |
| 40 kFixedSlot, | 44 kFixedSlot, |
| 41 kExplicit, | 45 kExplicit, |
| 42 kImmediate, | 46 kImmediate, |
| 43 kNone, | 47 kNone, |
| 44 kConstant, | 48 kConstant, |
| 45 kUnique, | 49 kUnique, |
| 46 kUniqueRegister | 50 kUniqueRegister |
| 47 }; | 51 }; |
| 48 | 52 |
| 49 struct TestOperand { | 53 struct TestOperand { |
| 50 TestOperand() : type_(kInvalid), vreg_(), value_(kNoValue) {} | 54 TestOperand() : type_(kInvalid), vreg_(), value_(kNoValue), rep_(kNoRep) {} |
| 51 TestOperand(TestOperandType type, int imm) | 55 explicit TestOperand(TestOperandType type) |
| 52 : type_(type), vreg_(), value_(imm) {} | 56 : type_(type), vreg_(), value_(kNoValue), rep_(kNoRep) {} |
| 57 // For tests that do register allocation. |
| 53 TestOperand(TestOperandType type, VReg vreg, int value = kNoValue) | 58 TestOperand(TestOperandType type, VReg vreg, int value = kNoValue) |
| 54 : type_(type), vreg_(vreg), value_(value) {} | 59 : type_(type), vreg_(vreg), value_(value), rep_(vreg.rep_) {} |
| 60 // For immediates, constants, and tests that don't do register allocation. |
| 61 TestOperand(TestOperandType type, int value, |
| 62 MachineRepresentation rep = kNoRep) |
| 63 : type_(type), vreg_(), value_(value), rep_(rep) {} |
| 55 | 64 |
| 56 TestOperandType type_; | 65 TestOperandType type_; |
| 57 VReg vreg_; | 66 VReg vreg_; |
| 58 int value_; | 67 int value_; |
| 68 MachineRepresentation rep_; |
| 59 }; | 69 }; |
| 60 | 70 |
| 61 static TestOperand Same() { return TestOperand(kSameAsFirst, VReg()); } | 71 static TestOperand Same() { return TestOperand(kSameAsFirst); } |
| 62 | 72 |
| 63 static TestOperand ExplicitReg(int index) { | 73 static TestOperand ExplicitReg(int index) { |
| 64 TestOperandType type = kExplicit; | 74 TestOperandType type = kExplicit; |
| 65 return TestOperand(type, VReg(), index); | 75 return TestOperand(type, index); |
| 76 } |
| 77 |
| 78 static TestOperand ExplicitFPReg(int index, |
| 79 MachineRepresentation rep = kFloat64) { |
| 80 TestOperandType type = kExplicit; |
| 81 return TestOperand(type, index, rep); |
| 66 } | 82 } |
| 67 | 83 |
| 68 static TestOperand Reg(VReg vreg, int index = kNoValue) { | 84 static TestOperand Reg(VReg vreg, int index = kNoValue) { |
| 69 TestOperandType type = kRegister; | 85 TestOperandType type = (index == kNoValue) ? kRegister : kFixedRegister; |
| 70 if (index != kNoValue) type = kFixedRegister; | |
| 71 return TestOperand(type, vreg, index); | 86 return TestOperand(type, vreg, index); |
| 72 } | 87 } |
| 73 | 88 |
| 74 static TestOperand Reg(int index = kNoValue) { return Reg(VReg(), index); } | 89 static TestOperand Reg(int index = kNoValue, |
| 90 MachineRepresentation rep = kNoRep) { |
| 91 return Reg(VReg(kNoValue, rep), index); |
| 92 } |
| 93 |
| 94 static TestOperand FPReg(int index = kNoValue, |
| 95 MachineRepresentation rep = kFloat64) { |
| 96 return Reg(index, rep); |
| 97 } |
| 75 | 98 |
| 76 static TestOperand Slot(VReg vreg, int index = kNoValue) { | 99 static TestOperand Slot(VReg vreg, int index = kNoValue) { |
| 77 TestOperandType type = kSlot; | 100 TestOperandType type = (index == kNoValue) ? kSlot : kFixedSlot; |
| 78 if (index != kNoValue) type = kFixedSlot; | |
| 79 return TestOperand(type, vreg, index); | 101 return TestOperand(type, vreg, index); |
| 80 } | 102 } |
| 81 | 103 |
| 82 static TestOperand Slot(int index = kNoValue) { return Slot(VReg(), index); } | 104 static TestOperand Slot(int index = kNoValue, |
| 105 MachineRepresentation rep = kNoRep) { |
| 106 return Slot(VReg(kNoValue, rep), index); |
| 107 } |
| 83 | 108 |
| 84 static TestOperand Const(int index) { | 109 static TestOperand Const(int index) { |
| 85 CHECK_NE(kNoValue, index); | 110 CHECK_NE(kNoValue, index); |
| 86 return TestOperand(kConstant, VReg(), index); | 111 return TestOperand(kConstant, index); |
| 87 } | 112 } |
| 88 | 113 |
| 89 static TestOperand Use(VReg vreg) { return TestOperand(kNone, vreg); } | 114 static TestOperand Use(VReg vreg) { return TestOperand(kNone, vreg); } |
| 90 | 115 |
| 91 static TestOperand Use() { return Use(VReg()); } | 116 static TestOperand Use() { return Use(VReg()); } |
| 92 | 117 |
| 93 static TestOperand Unique(VReg vreg) { return TestOperand(kUnique, vreg); } | 118 static TestOperand Unique(VReg vreg) { return TestOperand(kUnique, vreg); } |
| 94 | 119 |
| 95 static TestOperand UniqueReg(VReg vreg) { | 120 static TestOperand UniqueReg(VReg vreg) { |
| 96 return TestOperand(kUniqueRegister, vreg); | 121 return TestOperand(kUniqueRegister, vreg); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 122 } | 147 } |
| 123 | 148 |
| 124 static BlockCompletion Last() { | 149 static BlockCompletion Last() { |
| 125 BlockCompletion completion = {kBlockEnd, TestOperand(), kNoValue, kNoValue}; | 150 BlockCompletion completion = {kBlockEnd, TestOperand(), kNoValue, kNoValue}; |
| 126 return completion; | 151 return completion; |
| 127 } | 152 } |
| 128 | 153 |
| 129 InstructionSequenceTest(); | 154 InstructionSequenceTest(); |
| 130 | 155 |
| 131 void SetNumRegs(int num_general_registers, int num_double_registers); | 156 void SetNumRegs(int num_general_registers, int num_double_registers); |
| 157 int GetNumRegs(MachineRepresentation rep); |
| 158 int GetAllocatableCode(int index, MachineRepresentation rep = kNoRep); |
| 132 RegisterConfiguration* config(); | 159 RegisterConfiguration* config(); |
| 133 InstructionSequence* sequence(); | 160 InstructionSequence* sequence(); |
| 134 | 161 |
| 135 void StartLoop(int loop_blocks); | 162 void StartLoop(int loop_blocks); |
| 136 void EndLoop(); | 163 void EndLoop(); |
| 137 void StartBlock(bool deferred = false); | 164 void StartBlock(bool deferred = false); |
| 138 Instruction* EndBlock(BlockCompletion completion = FallThrough()); | 165 Instruction* EndBlock(BlockCompletion completion = FallThrough()); |
| 139 | 166 |
| 140 TestOperand Imm(int32_t imm = 0); | 167 TestOperand Imm(int32_t imm = 0); |
| 141 VReg Define(TestOperand output_op); | 168 VReg Define(TestOperand output_op); |
| 142 VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); } | 169 VReg Parameter(TestOperand output_op = Reg()) { return Define(output_op); } |
| 170 VReg FPParameter(MachineRepresentation rep = kFloat64) { |
| 171 return Parameter(FPReg(kNoValue, rep)); |
| 172 } |
| 173 |
| 174 MachineRepresentation GetCanonicalRep(TestOperand op) { |
| 175 return IsFloatingPoint(op.rep_) ? op.rep_ |
| 176 : sequence()->DefaultRepresentation(); |
| 177 } |
| 143 | 178 |
| 144 Instruction* Return(TestOperand input_op_0); | 179 Instruction* Return(TestOperand input_op_0); |
| 145 Instruction* Return(VReg vreg) { return Return(Reg(vreg, 0)); } | 180 Instruction* Return(VReg vreg) { return Return(Reg(vreg, 0)); } |
| 146 | 181 |
| 147 PhiInstruction* Phi(VReg incoming_vreg_0 = VReg(), | 182 PhiInstruction* Phi(VReg incoming_vreg_0 = VReg(), |
| 148 VReg incoming_vreg_1 = VReg(), | 183 VReg incoming_vreg_1 = VReg(), |
| 149 VReg incoming_vreg_2 = VReg(), | 184 VReg incoming_vreg_2 = VReg(), |
| 150 VReg incoming_vreg_3 = VReg()); | 185 VReg incoming_vreg_3 = VReg()); |
| 151 PhiInstruction* Phi(VReg incoming_vreg_0, size_t input_count); | 186 PhiInstruction* Phi(VReg incoming_vreg_0, size_t input_count); |
| 152 void SetInput(PhiInstruction* phi, size_t input, VReg vreg); | 187 void SetInput(PhiInstruction* phi, size_t input, VReg vreg); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 170 TestOperand input_op_1 = TestOperand(), | 205 TestOperand input_op_1 = TestOperand(), |
| 171 TestOperand input_op_2 = TestOperand(), | 206 TestOperand input_op_2 = TestOperand(), |
| 172 TestOperand input_op_3 = TestOperand()); | 207 TestOperand input_op_3 = TestOperand()); |
| 173 VReg EmitCall(TestOperand output_op, size_t input_size, TestOperand* inputs); | 208 VReg EmitCall(TestOperand output_op, size_t input_size, TestOperand* inputs); |
| 174 VReg EmitCall(TestOperand output_op, TestOperand input_op_0 = TestOperand(), | 209 VReg EmitCall(TestOperand output_op, TestOperand input_op_0 = TestOperand(), |
| 175 TestOperand input_op_1 = TestOperand(), | 210 TestOperand input_op_1 = TestOperand(), |
| 176 TestOperand input_op_2 = TestOperand(), | 211 TestOperand input_op_2 = TestOperand(), |
| 177 TestOperand input_op_3 = TestOperand()); | 212 TestOperand input_op_3 = TestOperand()); |
| 178 | 213 |
| 179 InstructionBlock* current_block() const { return current_block_; } | 214 InstructionBlock* current_block() const { return current_block_; } |
| 180 int num_general_registers() const { return num_general_registers_; } | |
| 181 int num_double_registers() const { return num_double_registers_; } | |
| 182 | 215 |
| 183 // Called after all instructions have been inserted. | 216 // Called after all instructions have been inserted. |
| 184 void WireBlocks(); | 217 void WireBlocks(); |
| 185 | 218 |
| 186 private: | 219 private: |
| 187 VReg NewReg() { return VReg(sequence()->NextVirtualRegister()); } | 220 virtual bool DoesRegisterAllocation() const { return true; } |
| 188 | 221 |
| 189 static TestOperand Invalid() { return TestOperand(kInvalid, VReg()); } | 222 VReg NewReg(TestOperand op = TestOperand()) { |
| 223 int vreg = sequence()->NextVirtualRegister(); |
| 224 if (IsFloatingPoint(op.rep_)) |
| 225 sequence()->MarkAsRepresentation(op.rep_, vreg); |
| 226 return VReg(vreg, op.rep_); |
| 227 } |
| 228 |
| 229 static TestOperand Invalid() { return TestOperand(kInvalid); } |
| 190 | 230 |
| 191 Instruction* EmitBranch(TestOperand input_op); | 231 Instruction* EmitBranch(TestOperand input_op); |
| 192 Instruction* EmitFallThrough(); | 232 Instruction* EmitFallThrough(); |
| 193 Instruction* EmitJump(); | 233 Instruction* EmitJump(); |
| 194 Instruction* NewInstruction(InstructionCode code, size_t outputs_size, | 234 Instruction* NewInstruction(InstructionCode code, size_t outputs_size, |
| 195 InstructionOperand* outputs, | 235 InstructionOperand* outputs, |
| 196 size_t inputs_size = 0, | 236 size_t inputs_size = 0, |
| 197 InstructionOperand* inputs = nullptr, | 237 InstructionOperand* inputs = nullptr, |
| 198 size_t temps_size = 0, | 238 size_t temps_size = 0, |
| 199 InstructionOperand* temps = nullptr); | 239 InstructionOperand* temps = nullptr); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 bool block_returns_; | 285 bool block_returns_; |
| 246 | 286 |
| 247 DISALLOW_COPY_AND_ASSIGN(InstructionSequenceTest); | 287 DISALLOW_COPY_AND_ASSIGN(InstructionSequenceTest); |
| 248 }; | 288 }; |
| 249 | 289 |
| 250 } // namespace compiler | 290 } // namespace compiler |
| 251 } // namespace internal | 291 } // namespace internal |
| 252 } // namespace v8 | 292 } // namespace v8 |
| 253 | 293 |
| 254 #endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_ | 294 #endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SEQUENCE_UNITTEST_H_ |
| OLD | NEW |