| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2016 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/instruction.h" | 
|  | 6 #include "src/register-configuration.h" | 
|  | 7 #include "test/unittests/test-utils.h" | 
|  | 8 #include "testing/gtest-support.h" | 
|  | 9 | 
|  | 10 namespace v8 { | 
|  | 11 namespace internal { | 
|  | 12 namespace compiler { | 
|  | 13 | 
|  | 14 namespace { | 
|  | 15 | 
|  | 16 const MachineRepresentation kWord = MachineRepresentation::kWord32; | 
|  | 17 const MachineRepresentation kFloat = MachineRepresentation::kFloat32; | 
|  | 18 const MachineRepresentation kDouble = MachineRepresentation::kFloat64; | 
|  | 19 | 
|  | 20 bool Interfere(LocationOperand::LocationKind kind, MachineRepresentation rep1, | 
|  | 21                int index1, MachineRepresentation rep2, int index2) { | 
|  | 22   return AllocatedOperand(kind, rep1, index1) | 
|  | 23       .InterferesWith(AllocatedOperand(kind, rep2, index2)); | 
|  | 24 } | 
|  | 25 | 
|  | 26 bool Contains(const ZoneVector<MoveOperands*>* moves, | 
|  | 27               const InstructionOperand& to, const InstructionOperand& from) { | 
|  | 28   for (auto move : *moves) { | 
|  | 29     if (move->destination().Equals(to) && move->source().Equals(from)) { | 
|  | 30       return true; | 
|  | 31     } | 
|  | 32   } | 
|  | 33   return false; | 
|  | 34 } | 
|  | 35 | 
|  | 36 }  // namespace | 
|  | 37 | 
|  | 38 class InstructionTest : public TestWithZone { | 
|  | 39  public: | 
|  | 40   InstructionTest() {} | 
|  | 41   virtual ~InstructionTest() {} | 
|  | 42 | 
|  | 43   ParallelMove* CreateParallelMove( | 
|  | 44       const std::vector<InstructionOperand>& operand_pairs) { | 
|  | 45     ParallelMove* parallel_move = new (zone()) ParallelMove(zone()); | 
|  | 46     for (size_t i = 0; i < operand_pairs.size(); i += 2) | 
|  | 47       parallel_move->AddMove(operand_pairs[i + 1], operand_pairs[i]); | 
|  | 48     return parallel_move; | 
|  | 49   } | 
|  | 50 }; | 
|  | 51 | 
|  | 52 TEST_F(InstructionTest, OperandInterference) { | 
|  | 53   // All general registers and slots interfere only with themselves. | 
|  | 54   for (int i = 0; i < RegisterConfiguration::kMaxGeneralRegisters; ++i) { | 
|  | 55     EXPECT_TRUE(Interfere(LocationOperand::REGISTER, kWord, i, kWord, i)); | 
|  | 56     EXPECT_TRUE(Interfere(LocationOperand::STACK_SLOT, kWord, i, kWord, i)); | 
|  | 57     for (int j = i + 1; j < RegisterConfiguration::kMaxGeneralRegisters; ++j) { | 
|  | 58       EXPECT_FALSE(Interfere(LocationOperand::REGISTER, kWord, i, kWord, j)); | 
|  | 59       EXPECT_FALSE(Interfere(LocationOperand::STACK_SLOT, kWord, i, kWord, j)); | 
|  | 60     } | 
|  | 61   } | 
|  | 62 | 
|  | 63   // All FP registers interfere with themselves. | 
|  | 64   for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) { | 
|  | 65     EXPECT_TRUE(Interfere(LocationOperand::REGISTER, kFloat, i, kFloat, i)); | 
|  | 66     EXPECT_TRUE(Interfere(LocationOperand::STACK_SLOT, kFloat, i, kFloat, i)); | 
|  | 67     EXPECT_TRUE(Interfere(LocationOperand::REGISTER, kDouble, i, kDouble, i)); | 
|  | 68     EXPECT_TRUE(Interfere(LocationOperand::STACK_SLOT, kDouble, i, kDouble, i)); | 
|  | 69   } | 
|  | 70 | 
|  | 71   if (kSimpleFPAliasing) { | 
|  | 72     // Simple FP aliasing: interfering registers of different reps have the same | 
|  | 73     // index. | 
|  | 74     for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) { | 
|  | 75       EXPECT_TRUE(Interfere(LocationOperand::REGISTER, kFloat, i, kDouble, i)); | 
|  | 76       EXPECT_TRUE(Interfere(LocationOperand::REGISTER, kDouble, i, kFloat, i)); | 
|  | 77       for (int j = i + 1; j < RegisterConfiguration::kMaxFPRegisters; ++j) { | 
|  | 78         EXPECT_FALSE(Interfere(LocationOperand::REGISTER, kWord, i, kWord, j)); | 
|  | 79         EXPECT_FALSE( | 
|  | 80             Interfere(LocationOperand::STACK_SLOT, kWord, i, kWord, j)); | 
|  | 81       } | 
|  | 82     } | 
|  | 83   } else { | 
|  | 84     // Complex FP aliasing: sub-registers intefere with containing registers. | 
|  | 85     // Test sub-register indices which may not exist on the platform. This is | 
|  | 86     // necessary since the GapResolver may split large moves into smaller ones. | 
|  | 87     for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) { | 
|  | 88       EXPECT_TRUE( | 
|  | 89           Interfere(LocationOperand::REGISTER, kFloat, i * 2, kDouble, i)); | 
|  | 90       EXPECT_TRUE( | 
|  | 91           Interfere(LocationOperand::REGISTER, kFloat, i * 2 + 1, kDouble, i)); | 
|  | 92       EXPECT_TRUE( | 
|  | 93           Interfere(LocationOperand::REGISTER, kDouble, i, kFloat, i * 2)); | 
|  | 94       EXPECT_TRUE( | 
|  | 95           Interfere(LocationOperand::REGISTER, kDouble, i, kFloat, i * 2 + 1)); | 
|  | 96 | 
|  | 97       for (int j = i + 1; j < RegisterConfiguration::kMaxFPRegisters; ++j) { | 
|  | 98         EXPECT_FALSE( | 
|  | 99             Interfere(LocationOperand::REGISTER, kFloat, i * 2, kDouble, j)); | 
|  | 100         EXPECT_FALSE(Interfere(LocationOperand::REGISTER, kFloat, i * 2 + 1, | 
|  | 101                                kDouble, j)); | 
|  | 102         EXPECT_FALSE( | 
|  | 103             Interfere(LocationOperand::REGISTER, kDouble, i, kFloat, j * 2)); | 
|  | 104         EXPECT_FALSE(Interfere(LocationOperand::REGISTER, kDouble, i, kFloat, | 
|  | 105                                j * 2 + 1)); | 
|  | 106       } | 
|  | 107     } | 
|  | 108   } | 
|  | 109 } | 
|  | 110 | 
|  | 111 TEST_F(InstructionTest, PrepareInsertAfter) { | 
|  | 112   InstructionOperand r0 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 113                                            MachineRepresentation::kWord32, 0); | 
|  | 114   InstructionOperand r1 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 115                                            MachineRepresentation::kWord32, 1); | 
|  | 116   InstructionOperand r2 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 117                                            MachineRepresentation::kWord32, 2); | 
|  | 118 | 
|  | 119   InstructionOperand d0 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 120                                            MachineRepresentation::kFloat64, 0); | 
|  | 121   InstructionOperand d1 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 122                                            MachineRepresentation::kFloat64, 1); | 
|  | 123   InstructionOperand d2 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 124                                            MachineRepresentation::kFloat64, 2); | 
|  | 125 | 
|  | 126   { | 
|  | 127     // Moves inserted after should pick up assignments to their sources. | 
|  | 128     // Moves inserted after should cause interfering moves to be eliminated. | 
|  | 129     ZoneVector<MoveOperands*> to_eliminate(zone()); | 
|  | 130     std::vector<InstructionOperand> moves = { | 
|  | 131         r1, r0,  // r1 <- r0 | 
|  | 132         r2, r0,  // r2 <- r0 | 
|  | 133         d1, d0,  // d1 <- d0 | 
|  | 134         d2, d0   // d2 <- d0 | 
|  | 135     }; | 
|  | 136 | 
|  | 137     ParallelMove* pm = CreateParallelMove(moves); | 
|  | 138     MoveOperands m1(r1, r2);  // r2 <- r1 | 
|  | 139     pm->PrepareInsertAfter(&m1, &to_eliminate); | 
|  | 140     CHECK(m1.source().Equals(r0)); | 
|  | 141     CHECK(Contains(&to_eliminate, r2, r0)); | 
|  | 142     MoveOperands m2(d1, d2);  // d2 <- d1 | 
|  | 143     pm->PrepareInsertAfter(&m2, &to_eliminate); | 
|  | 144     CHECK(m2.source().Equals(d0)); | 
|  | 145     CHECK(Contains(&to_eliminate, d2, d0)); | 
|  | 146   } | 
|  | 147 | 
|  | 148   if (!kSimpleFPAliasing) { | 
|  | 149     // Moves inserted after should cause all interfering moves to be eliminated. | 
|  | 150     auto s0 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 151                                MachineRepresentation::kFloat32, 0); | 
|  | 152     auto s1 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 153                                MachineRepresentation::kFloat32, 1); | 
|  | 154     auto s2 = AllocatedOperand(LocationOperand::REGISTER, | 
|  | 155                                MachineRepresentation::kFloat32, 2); | 
|  | 156 | 
|  | 157     { | 
|  | 158       ZoneVector<MoveOperands*> to_eliminate(zone()); | 
|  | 159       std::vector<InstructionOperand> moves = { | 
|  | 160           s0, s2,  // s0 <- s2 | 
|  | 161           s1, s2   // s1 <- s2 | 
|  | 162       }; | 
|  | 163 | 
|  | 164       ParallelMove* pm = CreateParallelMove(moves); | 
|  | 165       MoveOperands m1(d1, d0);  // d0 <- d1 | 
|  | 166       pm->PrepareInsertAfter(&m1, &to_eliminate); | 
|  | 167       CHECK(Contains(&to_eliminate, s0, s2)); | 
|  | 168       CHECK(Contains(&to_eliminate, s1, s2)); | 
|  | 169     } | 
|  | 170   } | 
|  | 171 } | 
|  | 172 | 
|  | 173 }  // namespace compiler | 
|  | 174 }  // namespace internal | 
|  | 175 }  // namespace v8 | 
| OLD | NEW | 
|---|