| 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 #include "test/unittests/compiler/instruction-selector-unittest.h" | 5 #include "test/unittests/compiler/instruction-selector-unittest.h" |
| 6 | 6 |
| 7 namespace v8 { | 7 namespace v8 { |
| 8 namespace internal { | 8 namespace internal { |
| 9 namespace compiler { | 9 namespace compiler { |
| 10 | 10 |
| 11 namespace { | 11 namespace { |
| 12 | 12 |
| 13 // Immediates (random subset). | 13 // Immediates (random subset). |
| 14 const int32_t kImmediates[] = {kMinInt, -42, -1, 0, 1, 2, | 14 const int32_t kImmediates[] = {kMinInt, -42, -1, 0, 1, 2, |
| 15 3, 4, 5, 6, 7, 8, | 15 3, 4, 5, 6, 7, 8, |
| 16 16, 42, 0xff, 0xffff, 0x0f0f0f0f, kMaxInt}; | 16 16, 42, 0xff, 0xffff, 0x0f0f0f0f, kMaxInt}; |
| 17 | 17 |
| 18 } // namespace | 18 } // namespace |
| 19 | 19 |
| 20 | 20 |
| 21 TEST_F(InstructionSelectorTest, Int32AddWithParameter) { | 21 TEST_F(InstructionSelectorTest, Int32AddWithParameter) { |
| 22 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 22 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), |
| 23 MachineType::Int32()); |
| 23 m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1))); | 24 m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1))); |
| 24 Stream s = m.Build(); | 25 Stream s = m.Build(); |
| 25 ASSERT_EQ(1U, s.size()); | 26 ASSERT_EQ(1U, s.size()); |
| 26 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 27 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); |
| 27 } | 28 } |
| 28 | 29 |
| 29 | 30 |
| 30 TEST_F(InstructionSelectorTest, Int32AddWithImmediate) { | 31 TEST_F(InstructionSelectorTest, Int32AddWithImmediate) { |
| 31 TRACED_FOREACH(int32_t, imm, kImmediates) { | 32 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 32 { | 33 { |
| 33 StreamBuilder m(this, kMachInt32, kMachInt32); | 34 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 34 m.Return(m.Int32Add(m.Parameter(0), m.Int32Constant(imm))); | 35 m.Return(m.Int32Add(m.Parameter(0), m.Int32Constant(imm))); |
| 35 Stream s = m.Build(); | 36 Stream s = m.Build(); |
| 36 ASSERT_EQ(1U, s.size()); | 37 ASSERT_EQ(1U, s.size()); |
| 37 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 38 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); |
| 38 if (imm == 0) { | 39 if (imm == 0) { |
| 39 ASSERT_EQ(1U, s[0]->InputCount()); | 40 ASSERT_EQ(1U, s[0]->InputCount()); |
| 40 } else { | 41 } else { |
| 41 ASSERT_EQ(2U, s[0]->InputCount()); | 42 ASSERT_EQ(2U, s[0]->InputCount()); |
| 42 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 43 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 43 } | 44 } |
| 44 } | 45 } |
| 45 { | 46 { |
| 46 StreamBuilder m(this, kMachInt32, kMachInt32); | 47 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 47 m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0))); | 48 m.Return(m.Int32Add(m.Int32Constant(imm), m.Parameter(0))); |
| 48 Stream s = m.Build(); | 49 Stream s = m.Build(); |
| 49 ASSERT_EQ(1U, s.size()); | 50 ASSERT_EQ(1U, s.size()); |
| 50 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 51 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); |
| 51 if (imm == 0) { | 52 if (imm == 0) { |
| 52 ASSERT_EQ(1U, s[0]->InputCount()); | 53 ASSERT_EQ(1U, s[0]->InputCount()); |
| 53 } else { | 54 } else { |
| 54 ASSERT_EQ(2U, s[0]->InputCount()); | 55 ASSERT_EQ(2U, s[0]->InputCount()); |
| 55 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 56 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 56 } | 57 } |
| 57 } | 58 } |
| 58 } | 59 } |
| 59 } | 60 } |
| 60 | 61 |
| 61 | 62 |
| 62 TEST_F(InstructionSelectorTest, Int32SubWithParameter) { | 63 TEST_F(InstructionSelectorTest, Int32SubWithParameter) { |
| 63 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 64 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), |
| 65 MachineType::Int32()); |
| 64 m.Return(m.Int32Sub(m.Parameter(0), m.Parameter(1))); | 66 m.Return(m.Int32Sub(m.Parameter(0), m.Parameter(1))); |
| 65 Stream s = m.Build(); | 67 Stream s = m.Build(); |
| 66 ASSERT_EQ(1U, s.size()); | 68 ASSERT_EQ(1U, s.size()); |
| 67 EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); | 69 EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); |
| 68 EXPECT_EQ(1U, s[0]->OutputCount()); | 70 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 69 } | 71 } |
| 70 | 72 |
| 71 | 73 |
| 72 TEST_F(InstructionSelectorTest, Int32SubWithImmediate) { | 74 TEST_F(InstructionSelectorTest, Int32SubWithImmediate) { |
| 73 TRACED_FOREACH(int32_t, imm, kImmediates) { | 75 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 74 StreamBuilder m(this, kMachInt32, kMachInt32); | 76 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 75 m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm))); | 77 m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm))); |
| 76 Stream s = m.Build(); | 78 Stream s = m.Build(); |
| 77 ASSERT_EQ(1U, s.size()); | 79 ASSERT_EQ(1U, s.size()); |
| 78 EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); | 80 EXPECT_EQ(kIA32Sub, s[0]->arch_opcode()); |
| 79 ASSERT_EQ(2U, s[0]->InputCount()); | 81 ASSERT_EQ(2U, s[0]->InputCount()); |
| 80 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 82 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 81 } | 83 } |
| 82 } | 84 } |
| 83 | 85 |
| 84 | 86 |
| 85 // ----------------------------------------------------------------------------- | 87 // ----------------------------------------------------------------------------- |
| 86 // Conversions. | 88 // Conversions. |
| 87 | 89 |
| 88 | 90 |
| 89 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) { | 91 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) { |
| 90 StreamBuilder m(this, kMachFloat32, kMachFloat64); | 92 StreamBuilder m(this, MachineType::Float32(), MachineType::Float64()); |
| 91 m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0))); | 93 m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0))); |
| 92 Stream s = m.Build(); | 94 Stream s = m.Build(); |
| 93 ASSERT_EQ(1U, s.size()); | 95 ASSERT_EQ(1U, s.size()); |
| 94 EXPECT_EQ(kSSEFloat32ToFloat64, s[0]->arch_opcode()); | 96 EXPECT_EQ(kSSEFloat32ToFloat64, s[0]->arch_opcode()); |
| 95 EXPECT_EQ(1U, s[0]->InputCount()); | 97 EXPECT_EQ(1U, s[0]->InputCount()); |
| 96 EXPECT_EQ(1U, s[0]->OutputCount()); | 98 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 97 } | 99 } |
| 98 | 100 |
| 99 | 101 |
| 100 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) { | 102 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) { |
| 101 StreamBuilder m(this, kMachFloat64, kMachFloat32); | 103 StreamBuilder m(this, MachineType::Float64(), MachineType::Float32()); |
| 102 m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0))); | 104 m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0))); |
| 103 Stream s = m.Build(); | 105 Stream s = m.Build(); |
| 104 ASSERT_EQ(1U, s.size()); | 106 ASSERT_EQ(1U, s.size()); |
| 105 EXPECT_EQ(kSSEFloat64ToFloat32, s[0]->arch_opcode()); | 107 EXPECT_EQ(kSSEFloat64ToFloat32, s[0]->arch_opcode()); |
| 106 EXPECT_EQ(1U, s[0]->InputCount()); | 108 EXPECT_EQ(1U, s[0]->InputCount()); |
| 107 EXPECT_EQ(1U, s[0]->OutputCount()); | 109 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 108 } | 110 } |
| 109 | 111 |
| 110 | 112 |
| 111 // ----------------------------------------------------------------------------- | 113 // ----------------------------------------------------------------------------- |
| 112 // Better left operand for commutative binops | 114 // Better left operand for commutative binops |
| 113 | 115 |
| 114 | 116 |
| 115 TEST_F(InstructionSelectorTest, BetterLeftOperandTestAddBinop) { | 117 TEST_F(InstructionSelectorTest, BetterLeftOperandTestAddBinop) { |
| 116 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 118 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), |
| 119 MachineType::Int32()); |
| 117 Node* param1 = m.Parameter(0); | 120 Node* param1 = m.Parameter(0); |
| 118 Node* param2 = m.Parameter(1); | 121 Node* param2 = m.Parameter(1); |
| 119 Node* add = m.Int32Add(param1, param2); | 122 Node* add = m.Int32Add(param1, param2); |
| 120 m.Return(m.Int32Add(add, param1)); | 123 m.Return(m.Int32Add(add, param1)); |
| 121 Stream s = m.Build(); | 124 Stream s = m.Build(); |
| 122 ASSERT_EQ(2U, s.size()); | 125 ASSERT_EQ(2U, s.size()); |
| 123 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 126 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); |
| 124 ASSERT_EQ(2U, s[0]->InputCount()); | 127 ASSERT_EQ(2U, s[0]->InputCount()); |
| 125 ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated()); | 128 ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated()); |
| 126 EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0))); | 129 EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0))); |
| 127 EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(1))); | 130 EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(1))); |
| 128 ASSERT_EQ(2U, s[1]->InputCount()); | 131 ASSERT_EQ(2U, s[1]->InputCount()); |
| 129 EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0))); | 132 EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(0))); |
| 130 } | 133 } |
| 131 | 134 |
| 132 | 135 |
| 133 TEST_F(InstructionSelectorTest, BetterLeftOperandTestMulBinop) { | 136 TEST_F(InstructionSelectorTest, BetterLeftOperandTestMulBinop) { |
| 134 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 137 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), |
| 138 MachineType::Int32()); |
| 135 Node* param1 = m.Parameter(0); | 139 Node* param1 = m.Parameter(0); |
| 136 Node* param2 = m.Parameter(1); | 140 Node* param2 = m.Parameter(1); |
| 137 Node* mul = m.Int32Mul(param1, param2); | 141 Node* mul = m.Int32Mul(param1, param2); |
| 138 m.Return(m.Int32Mul(mul, param1)); | 142 m.Return(m.Int32Mul(mul, param1)); |
| 139 Stream s = m.Build(); | 143 Stream s = m.Build(); |
| 140 ASSERT_EQ(2U, s.size()); | 144 ASSERT_EQ(2U, s.size()); |
| 141 EXPECT_EQ(kIA32Imul, s[0]->arch_opcode()); | 145 EXPECT_EQ(kIA32Imul, s[0]->arch_opcode()); |
| 142 ASSERT_EQ(2U, s[0]->InputCount()); | 146 ASSERT_EQ(2U, s[0]->InputCount()); |
| 143 ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated()); | 147 ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated()); |
| 144 EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(0))); | 148 EXPECT_EQ(s.ToVreg(param2), s.ToVreg(s[0]->InputAt(0))); |
| 145 EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(1))); | 149 EXPECT_EQ(s.ToVreg(param1), s.ToVreg(s[0]->InputAt(1))); |
| 146 } | 150 } |
| 147 | 151 |
| 148 | 152 |
| 149 // ----------------------------------------------------------------------------- | 153 // ----------------------------------------------------------------------------- |
| 150 // Conversions. | 154 // Conversions. |
| 151 | 155 |
| 152 | 156 |
| 153 TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) { | 157 TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) { |
| 154 StreamBuilder m(this, kMachFloat64, kMachUint32); | 158 StreamBuilder m(this, MachineType::Float64(), MachineType::Uint32()); |
| 155 m.Return(m.ChangeUint32ToFloat64(m.Parameter(0))); | 159 m.Return(m.ChangeUint32ToFloat64(m.Parameter(0))); |
| 156 Stream s = m.Build(); | 160 Stream s = m.Build(); |
| 157 ASSERT_EQ(1U, s.size()); | 161 ASSERT_EQ(1U, s.size()); |
| 158 EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode()); | 162 EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode()); |
| 159 } | 163 } |
| 160 | 164 |
| 161 | 165 |
| 162 // ----------------------------------------------------------------------------- | 166 // ----------------------------------------------------------------------------- |
| 163 // Loads and stores | 167 // Loads and stores |
| 164 | 168 |
| 165 | 169 |
| 166 namespace { | 170 namespace { |
| 167 | 171 |
| 168 struct MemoryAccess { | 172 struct MemoryAccess { |
| 169 MachineType type; | 173 MachineType type; |
| 170 ArchOpcode load_opcode; | 174 ArchOpcode load_opcode; |
| 171 ArchOpcode store_opcode; | 175 ArchOpcode store_opcode; |
| 172 }; | 176 }; |
| 173 | 177 |
| 174 | 178 |
| 175 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { | 179 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { |
| 176 return os << memacc.type; | 180 return os << memacc.type; |
| 177 } | 181 } |
| 178 | 182 |
| 179 | 183 |
| 180 static const MemoryAccess kMemoryAccesses[] = { | 184 static const MemoryAccess kMemoryAccesses[] = { |
| 181 {kMachInt8, kIA32Movsxbl, kIA32Movb}, | 185 {MachineType::Int8(), kIA32Movsxbl, kIA32Movb}, |
| 182 {kMachUint8, kIA32Movzxbl, kIA32Movb}, | 186 {MachineType::Uint8(), kIA32Movzxbl, kIA32Movb}, |
| 183 {kMachInt16, kIA32Movsxwl, kIA32Movw}, | 187 {MachineType::Int16(), kIA32Movsxwl, kIA32Movw}, |
| 184 {kMachUint16, kIA32Movzxwl, kIA32Movw}, | 188 {MachineType::Uint16(), kIA32Movzxwl, kIA32Movw}, |
| 185 {kMachInt32, kIA32Movl, kIA32Movl}, | 189 {MachineType::Int32(), kIA32Movl, kIA32Movl}, |
| 186 {kMachUint32, kIA32Movl, kIA32Movl}, | 190 {MachineType::Uint32(), kIA32Movl, kIA32Movl}, |
| 187 {kMachFloat32, kIA32Movss, kIA32Movss}, | 191 {MachineType::Float32(), kIA32Movss, kIA32Movss}, |
| 188 {kMachFloat64, kIA32Movsd, kIA32Movsd}}; | 192 {MachineType::Float64(), kIA32Movsd, kIA32Movsd}}; |
| 189 | 193 |
| 190 } // namespace | 194 } // namespace |
| 191 | 195 |
| 192 | 196 |
| 193 typedef InstructionSelectorTestWithParam<MemoryAccess> | 197 typedef InstructionSelectorTestWithParam<MemoryAccess> |
| 194 InstructionSelectorMemoryAccessTest; | 198 InstructionSelectorMemoryAccessTest; |
| 195 | 199 |
| 196 | 200 |
| 197 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | 201 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { |
| 198 const MemoryAccess memacc = GetParam(); | 202 const MemoryAccess memacc = GetParam(); |
| 199 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); | 203 StreamBuilder m(this, memacc.type, MachineType::Pointer(), |
| 204 MachineType::Int32()); |
| 200 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); | 205 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); |
| 201 Stream s = m.Build(); | 206 Stream s = m.Build(); |
| 202 ASSERT_EQ(1U, s.size()); | 207 ASSERT_EQ(1U, s.size()); |
| 203 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 208 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| 204 EXPECT_EQ(2U, s[0]->InputCount()); | 209 EXPECT_EQ(2U, s[0]->InputCount()); |
| 205 EXPECT_EQ(1U, s[0]->OutputCount()); | 210 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 206 } | 211 } |
| 207 | 212 |
| 208 | 213 |
| 209 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) { | 214 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateBase) { |
| 210 const MemoryAccess memacc = GetParam(); | 215 const MemoryAccess memacc = GetParam(); |
| 211 TRACED_FOREACH(int32_t, base, kImmediates) { | 216 TRACED_FOREACH(int32_t, base, kImmediates) { |
| 212 StreamBuilder m(this, memacc.type, kMachPtr); | 217 StreamBuilder m(this, memacc.type, MachineType::Pointer()); |
| 213 m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0))); | 218 m.Return(m.Load(memacc.type, m.Int32Constant(base), m.Parameter(0))); |
| 214 Stream s = m.Build(); | 219 Stream s = m.Build(); |
| 215 ASSERT_EQ(1U, s.size()); | 220 ASSERT_EQ(1U, s.size()); |
| 216 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 221 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| 217 if (base == 0) { | 222 if (base == 0) { |
| 218 ASSERT_EQ(1U, s[0]->InputCount()); | 223 ASSERT_EQ(1U, s[0]->InputCount()); |
| 219 } else { | 224 } else { |
| 220 ASSERT_EQ(2U, s[0]->InputCount()); | 225 ASSERT_EQ(2U, s[0]->InputCount()); |
| 221 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 226 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 222 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | 227 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); |
| 223 } | 228 } |
| 224 EXPECT_EQ(1U, s[0]->OutputCount()); | 229 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 225 } | 230 } |
| 226 } | 231 } |
| 227 | 232 |
| 228 | 233 |
| 229 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { | 234 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { |
| 230 const MemoryAccess memacc = GetParam(); | 235 const MemoryAccess memacc = GetParam(); |
| 231 TRACED_FOREACH(int32_t, index, kImmediates) { | 236 TRACED_FOREACH(int32_t, index, kImmediates) { |
| 232 StreamBuilder m(this, memacc.type, kMachPtr); | 237 StreamBuilder m(this, memacc.type, MachineType::Pointer()); |
| 233 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | 238 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); |
| 234 Stream s = m.Build(); | 239 Stream s = m.Build(); |
| 235 ASSERT_EQ(1U, s.size()); | 240 ASSERT_EQ(1U, s.size()); |
| 236 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | 241 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| 237 if (index == 0) { | 242 if (index == 0) { |
| 238 ASSERT_EQ(1U, s[0]->InputCount()); | 243 ASSERT_EQ(1U, s[0]->InputCount()); |
| 239 } else { | 244 } else { |
| 240 ASSERT_EQ(2U, s[0]->InputCount()); | 245 ASSERT_EQ(2U, s[0]->InputCount()); |
| 241 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 246 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 242 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | 247 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
| 243 } | 248 } |
| 244 EXPECT_EQ(1U, s[0]->OutputCount()); | 249 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 245 } | 250 } |
| 246 } | 251 } |
| 247 | 252 |
| 248 | 253 |
| 249 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | 254 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { |
| 250 const MemoryAccess memacc = GetParam(); | 255 const MemoryAccess memacc = GetParam(); |
| 251 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | 256 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), |
| 257 MachineType::Int32(), memacc.type); |
| 252 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2), | 258 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2), |
| 253 kNoWriteBarrier); | 259 kNoWriteBarrier); |
| 254 m.Return(m.Int32Constant(0)); | 260 m.Return(m.Int32Constant(0)); |
| 255 Stream s = m.Build(); | 261 Stream s = m.Build(); |
| 256 ASSERT_EQ(1U, s.size()); | 262 ASSERT_EQ(1U, s.size()); |
| 257 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 263 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
| 258 EXPECT_EQ(3U, s[0]->InputCount()); | 264 EXPECT_EQ(3U, s[0]->InputCount()); |
| 259 EXPECT_EQ(0U, s[0]->OutputCount()); | 265 EXPECT_EQ(0U, s[0]->OutputCount()); |
| 260 } | 266 } |
| 261 | 267 |
| 262 | 268 |
| 263 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) { | 269 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateBase) { |
| 264 const MemoryAccess memacc = GetParam(); | 270 const MemoryAccess memacc = GetParam(); |
| 265 TRACED_FOREACH(int32_t, base, kImmediates) { | 271 TRACED_FOREACH(int32_t, base, kImmediates) { |
| 266 StreamBuilder m(this, kMachInt32, kMachInt32, memacc.type); | 272 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), |
| 273 memacc.type); |
| 267 m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1), | 274 m.Store(memacc.type, m.Int32Constant(base), m.Parameter(0), m.Parameter(1), |
| 268 kNoWriteBarrier); | 275 kNoWriteBarrier); |
| 269 m.Return(m.Int32Constant(0)); | 276 m.Return(m.Int32Constant(0)); |
| 270 Stream s = m.Build(); | 277 Stream s = m.Build(); |
| 271 ASSERT_EQ(1U, s.size()); | 278 ASSERT_EQ(1U, s.size()); |
| 272 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 279 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
| 273 if (base == 0) { | 280 if (base == 0) { |
| 274 ASSERT_EQ(2U, s[0]->InputCount()); | 281 ASSERT_EQ(2U, s[0]->InputCount()); |
| 275 } else { | 282 } else { |
| 276 ASSERT_EQ(3U, s[0]->InputCount()); | 283 ASSERT_EQ(3U, s[0]->InputCount()); |
| 277 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 284 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 278 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); | 285 EXPECT_EQ(base, s.ToInt32(s[0]->InputAt(1))); |
| 279 } | 286 } |
| 280 EXPECT_EQ(0U, s[0]->OutputCount()); | 287 EXPECT_EQ(0U, s[0]->OutputCount()); |
| 281 } | 288 } |
| 282 } | 289 } |
| 283 | 290 |
| 284 | 291 |
| 285 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { | 292 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { |
| 286 const MemoryAccess memacc = GetParam(); | 293 const MemoryAccess memacc = GetParam(); |
| 287 TRACED_FOREACH(int32_t, index, kImmediates) { | 294 TRACED_FOREACH(int32_t, index, kImmediates) { |
| 288 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | 295 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), |
| 296 memacc.type); |
| 289 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), m.Parameter(1), | 297 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), m.Parameter(1), |
| 290 kNoWriteBarrier); | 298 kNoWriteBarrier); |
| 291 m.Return(m.Int32Constant(0)); | 299 m.Return(m.Int32Constant(0)); |
| 292 Stream s = m.Build(); | 300 Stream s = m.Build(); |
| 293 ASSERT_EQ(1U, s.size()); | 301 ASSERT_EQ(1U, s.size()); |
| 294 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | 302 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
| 295 if (index == 0) { | 303 if (index == 0) { |
| 296 ASSERT_EQ(2U, s[0]->InputCount()); | 304 ASSERT_EQ(2U, s[0]->InputCount()); |
| 297 } else { | 305 } else { |
| 298 ASSERT_EQ(3U, s[0]->InputCount()); | 306 ASSERT_EQ(3U, s[0]->InputCount()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 313 // AddressingMode for loads and stores. | 321 // AddressingMode for loads and stores. |
| 314 | 322 |
| 315 | 323 |
| 316 class AddressingModeUnitTest : public InstructionSelectorTest { | 324 class AddressingModeUnitTest : public InstructionSelectorTest { |
| 317 public: | 325 public: |
| 318 AddressingModeUnitTest() : m(NULL) { Reset(); } | 326 AddressingModeUnitTest() : m(NULL) { Reset(); } |
| 319 ~AddressingModeUnitTest() { delete m; } | 327 ~AddressingModeUnitTest() { delete m; } |
| 320 | 328 |
| 321 void Run(Node* base, Node* load_index, Node* store_index, | 329 void Run(Node* base, Node* load_index, Node* store_index, |
| 322 AddressingMode mode) { | 330 AddressingMode mode) { |
| 323 Node* load = m->Load(kMachInt32, base, load_index); | 331 Node* load = m->Load(MachineType::Int32(), base, load_index); |
| 324 m->Store(kMachInt32, base, store_index, load, kNoWriteBarrier); | 332 m->Store(MachineType::Int32(), base, store_index, load, kNoWriteBarrier); |
| 325 m->Return(m->Int32Constant(0)); | 333 m->Return(m->Int32Constant(0)); |
| 326 Stream s = m->Build(); | 334 Stream s = m->Build(); |
| 327 ASSERT_EQ(2U, s.size()); | 335 ASSERT_EQ(2U, s.size()); |
| 328 EXPECT_EQ(mode, s[0]->addressing_mode()); | 336 EXPECT_EQ(mode, s[0]->addressing_mode()); |
| 329 EXPECT_EQ(mode, s[1]->addressing_mode()); | 337 EXPECT_EQ(mode, s[1]->addressing_mode()); |
| 330 } | 338 } |
| 331 | 339 |
| 332 Node* zero; | 340 Node* zero; |
| 333 Node* null_ptr; | 341 Node* null_ptr; |
| 334 Node* non_zero; | 342 Node* non_zero; |
| 335 Node* base_reg; // opaque value to generate base as register | 343 Node* base_reg; // opaque value to generate base as register |
| 336 Node* index_reg; // opaque value to generate index as register | 344 Node* index_reg; // opaque value to generate index as register |
| 337 Node* scales[4]; | 345 Node* scales[4]; |
| 338 StreamBuilder* m; | 346 StreamBuilder* m; |
| 339 | 347 |
| 340 void Reset() { | 348 void Reset() { |
| 341 delete m; | 349 delete m; |
| 342 m = new StreamBuilder(this, kMachInt32, kMachInt32, kMachInt32); | 350 m = new StreamBuilder(this, MachineType::Int32(), MachineType::Int32(), |
| 351 MachineType::Int32()); |
| 343 zero = m->Int32Constant(0); | 352 zero = m->Int32Constant(0); |
| 344 null_ptr = m->Int32Constant(0); | 353 null_ptr = m->Int32Constant(0); |
| 345 non_zero = m->Int32Constant(127); | 354 non_zero = m->Int32Constant(127); |
| 346 base_reg = m->Parameter(0); | 355 base_reg = m->Parameter(0); |
| 347 index_reg = m->Parameter(0); | 356 index_reg = m->Parameter(0); |
| 348 | 357 |
| 349 scales[0] = m->Int32Constant(1); | 358 scales[0] = m->Int32Constant(1); |
| 350 scales[1] = m->Int32Constant(2); | 359 scales[1] = m->Int32Constant(2); |
| 351 scales[2] = m->Int32Constant(4); | 360 scales[2] = m->Int32Constant(4); |
| 352 scales[3] = m->Int32Constant(8); | 361 scales[3] = m->Int32Constant(8); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 return kMode_MRI; | 567 return kMode_MRI; |
| 559 default: | 568 default: |
| 560 UNREACHABLE(); | 569 UNREACHABLE(); |
| 561 return kMode_None; | 570 return kMode_None; |
| 562 } | 571 } |
| 563 } | 572 } |
| 564 | 573 |
| 565 | 574 |
| 566 TEST_P(InstructionSelectorMultTest, Mult32) { | 575 TEST_P(InstructionSelectorMultTest, Mult32) { |
| 567 const MultParam m_param = GetParam(); | 576 const MultParam m_param = GetParam(); |
| 568 StreamBuilder m(this, kMachInt32, kMachInt32); | 577 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 569 Node* param = m.Parameter(0); | 578 Node* param = m.Parameter(0); |
| 570 Node* mult = m.Int32Mul(param, m.Int32Constant(m_param.value)); | 579 Node* mult = m.Int32Mul(param, m.Int32Constant(m_param.value)); |
| 571 m.Return(mult); | 580 m.Return(mult); |
| 572 Stream s = m.Build(); | 581 Stream s = m.Build(); |
| 573 ASSERT_EQ(1U, s.size()); | 582 ASSERT_EQ(1U, s.size()); |
| 574 EXPECT_EQ(m_param.addressing_mode, s[0]->addressing_mode()); | 583 EXPECT_EQ(m_param.addressing_mode, s[0]->addressing_mode()); |
| 575 if (m_param.lea_expected) { | 584 if (m_param.lea_expected) { |
| 576 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 585 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); |
| 577 ASSERT_EQ(InputCountForLea(s[0]->addressing_mode()), s[0]->InputCount()); | 586 ASSERT_EQ(InputCountForLea(s[0]->addressing_mode()), s[0]->InputCount()); |
| 578 } else { | 587 } else { |
| 579 EXPECT_EQ(kIA32Imul, s[0]->arch_opcode()); | 588 EXPECT_EQ(kIA32Imul, s[0]->arch_opcode()); |
| 580 ASSERT_EQ(2U, s[0]->InputCount()); | 589 ASSERT_EQ(2U, s[0]->InputCount()); |
| 581 } | 590 } |
| 582 EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->InputAt(0))); | 591 EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->InputAt(0))); |
| 583 } | 592 } |
| 584 | 593 |
| 585 | 594 |
| 586 TEST_P(InstructionSelectorMultTest, MultAdd32) { | 595 TEST_P(InstructionSelectorMultTest, MultAdd32) { |
| 587 TRACED_FOREACH(int32_t, imm, kImmediates) { | 596 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 588 const MultParam m_param = GetParam(); | 597 const MultParam m_param = GetParam(); |
| 589 StreamBuilder m(this, kMachInt32, kMachInt32); | 598 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); |
| 590 Node* param = m.Parameter(0); | 599 Node* param = m.Parameter(0); |
| 591 Node* mult = m.Int32Add(m.Int32Mul(param, m.Int32Constant(m_param.value)), | 600 Node* mult = m.Int32Add(m.Int32Mul(param, m.Int32Constant(m_param.value)), |
| 592 m.Int32Constant(imm)); | 601 m.Int32Constant(imm)); |
| 593 m.Return(mult); | 602 m.Return(mult); |
| 594 Stream s = m.Build(); | 603 Stream s = m.Build(); |
| 595 if (m_param.lea_expected) { | 604 if (m_param.lea_expected) { |
| 596 ASSERT_EQ(1U, s.size()); | 605 ASSERT_EQ(1U, s.size()); |
| 597 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); | 606 EXPECT_EQ(kIA32Lea, s[0]->arch_opcode()); |
| 598 EXPECT_EQ(AddressingModeForAddMult(imm, m_param), | 607 EXPECT_EQ(AddressingModeForAddMult(imm, m_param), |
| 599 s[0]->addressing_mode()); | 608 s[0]->addressing_mode()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 611 } | 620 } |
| 612 } | 621 } |
| 613 } | 622 } |
| 614 | 623 |
| 615 | 624 |
| 616 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMultTest, | 625 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMultTest, |
| 617 ::testing::ValuesIn(kMultParams)); | 626 ::testing::ValuesIn(kMultParams)); |
| 618 | 627 |
| 619 | 628 |
| 620 TEST_F(InstructionSelectorTest, Int32MulHigh) { | 629 TEST_F(InstructionSelectorTest, Int32MulHigh) { |
| 621 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 630 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), |
| 631 MachineType::Int32()); |
| 622 Node* const p0 = m.Parameter(0); | 632 Node* const p0 = m.Parameter(0); |
| 623 Node* const p1 = m.Parameter(1); | 633 Node* const p1 = m.Parameter(1); |
| 624 Node* const n = m.Int32MulHigh(p0, p1); | 634 Node* const n = m.Int32MulHigh(p0, p1); |
| 625 m.Return(n); | 635 m.Return(n); |
| 626 Stream s = m.Build(); | 636 Stream s = m.Build(); |
| 627 ASSERT_EQ(1U, s.size()); | 637 ASSERT_EQ(1U, s.size()); |
| 628 EXPECT_EQ(kIA32ImulHigh, s[0]->arch_opcode()); | 638 EXPECT_EQ(kIA32ImulHigh, s[0]->arch_opcode()); |
| 629 ASSERT_EQ(2U, s[0]->InputCount()); | 639 ASSERT_EQ(2U, s[0]->InputCount()); |
| 630 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 640 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 631 EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), eax)); | 641 EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), eax)); |
| 632 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); | 642 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
| 633 EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1))); | 643 EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1))); |
| 634 ASSERT_EQ(1U, s[0]->OutputCount()); | 644 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 635 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 645 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 636 EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), edx)); | 646 EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), edx)); |
| 637 } | 647 } |
| 638 | 648 |
| 639 | 649 |
| 640 // ----------------------------------------------------------------------------- | 650 // ----------------------------------------------------------------------------- |
| 641 // Floating point operations. | 651 // Floating point operations. |
| 642 | 652 |
| 643 | 653 |
| 644 TEST_F(InstructionSelectorTest, Float32Abs) { | 654 TEST_F(InstructionSelectorTest, Float32Abs) { |
| 645 { | 655 { |
| 646 StreamBuilder m(this, kMachFloat32, kMachFloat32); | 656 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); |
| 647 Node* const p0 = m.Parameter(0); | 657 Node* const p0 = m.Parameter(0); |
| 648 Node* const n = m.Float32Abs(p0); | 658 Node* const n = m.Float32Abs(p0); |
| 649 m.Return(n); | 659 m.Return(n); |
| 650 Stream s = m.Build(); | 660 Stream s = m.Build(); |
| 651 ASSERT_EQ(1U, s.size()); | 661 ASSERT_EQ(1U, s.size()); |
| 652 EXPECT_EQ(kSSEFloat32Abs, s[0]->arch_opcode()); | 662 EXPECT_EQ(kSSEFloat32Abs, s[0]->arch_opcode()); |
| 653 ASSERT_EQ(1U, s[0]->InputCount()); | 663 ASSERT_EQ(1U, s[0]->InputCount()); |
| 654 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 664 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 655 ASSERT_EQ(1U, s[0]->OutputCount()); | 665 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 656 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); | 666 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); |
| 657 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 667 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 658 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 668 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 659 } | 669 } |
| 660 { | 670 { |
| 661 StreamBuilder m(this, kMachFloat32, kMachFloat32); | 671 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); |
| 662 Node* const p0 = m.Parameter(0); | 672 Node* const p0 = m.Parameter(0); |
| 663 Node* const n = m.Float32Abs(p0); | 673 Node* const n = m.Float32Abs(p0); |
| 664 m.Return(n); | 674 m.Return(n); |
| 665 Stream s = m.Build(AVX); | 675 Stream s = m.Build(AVX); |
| 666 ASSERT_EQ(1U, s.size()); | 676 ASSERT_EQ(1U, s.size()); |
| 667 EXPECT_EQ(kAVXFloat32Abs, s[0]->arch_opcode()); | 677 EXPECT_EQ(kAVXFloat32Abs, s[0]->arch_opcode()); |
| 668 ASSERT_EQ(1U, s[0]->InputCount()); | 678 ASSERT_EQ(1U, s[0]->InputCount()); |
| 669 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 679 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 670 ASSERT_EQ(1U, s[0]->OutputCount()); | 680 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 671 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 681 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 672 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 682 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 673 } | 683 } |
| 674 } | 684 } |
| 675 | 685 |
| 676 | 686 |
| 677 TEST_F(InstructionSelectorTest, Float64Abs) { | 687 TEST_F(InstructionSelectorTest, Float64Abs) { |
| 678 { | 688 { |
| 679 StreamBuilder m(this, kMachFloat64, kMachFloat64); | 689 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); |
| 680 Node* const p0 = m.Parameter(0); | 690 Node* const p0 = m.Parameter(0); |
| 681 Node* const n = m.Float64Abs(p0); | 691 Node* const n = m.Float64Abs(p0); |
| 682 m.Return(n); | 692 m.Return(n); |
| 683 Stream s = m.Build(); | 693 Stream s = m.Build(); |
| 684 ASSERT_EQ(1U, s.size()); | 694 ASSERT_EQ(1U, s.size()); |
| 685 EXPECT_EQ(kSSEFloat64Abs, s[0]->arch_opcode()); | 695 EXPECT_EQ(kSSEFloat64Abs, s[0]->arch_opcode()); |
| 686 ASSERT_EQ(1U, s[0]->InputCount()); | 696 ASSERT_EQ(1U, s[0]->InputCount()); |
| 687 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 697 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 688 ASSERT_EQ(1U, s[0]->OutputCount()); | 698 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 689 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); | 699 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); |
| 690 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 700 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 691 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 701 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 692 } | 702 } |
| 693 { | 703 { |
| 694 StreamBuilder m(this, kMachFloat64, kMachFloat64); | 704 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); |
| 695 Node* const p0 = m.Parameter(0); | 705 Node* const p0 = m.Parameter(0); |
| 696 Node* const n = m.Float64Abs(p0); | 706 Node* const n = m.Float64Abs(p0); |
| 697 m.Return(n); | 707 m.Return(n); |
| 698 Stream s = m.Build(AVX); | 708 Stream s = m.Build(AVX); |
| 699 ASSERT_EQ(1U, s.size()); | 709 ASSERT_EQ(1U, s.size()); |
| 700 EXPECT_EQ(kAVXFloat64Abs, s[0]->arch_opcode()); | 710 EXPECT_EQ(kAVXFloat64Abs, s[0]->arch_opcode()); |
| 701 ASSERT_EQ(1U, s[0]->InputCount()); | 711 ASSERT_EQ(1U, s[0]->InputCount()); |
| 702 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 712 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 703 ASSERT_EQ(1U, s[0]->OutputCount()); | 713 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 704 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 714 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 705 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 715 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 706 } | 716 } |
| 707 } | 717 } |
| 708 | 718 |
| 709 | 719 |
| 710 TEST_F(InstructionSelectorTest, Float64BinopArithmetic) { | 720 TEST_F(InstructionSelectorTest, Float64BinopArithmetic) { |
| 711 { | 721 { |
| 712 StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64); | 722 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), |
| 723 MachineType::Float64()); |
| 713 Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1)); | 724 Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1)); |
| 714 Node* mul = m.Float64Mul(add, m.Parameter(1)); | 725 Node* mul = m.Float64Mul(add, m.Parameter(1)); |
| 715 Node* sub = m.Float64Sub(mul, add); | 726 Node* sub = m.Float64Sub(mul, add); |
| 716 Node* ret = m.Float64Div(mul, sub); | 727 Node* ret = m.Float64Div(mul, sub); |
| 717 m.Return(ret); | 728 m.Return(ret); |
| 718 Stream s = m.Build(AVX); | 729 Stream s = m.Build(AVX); |
| 719 ASSERT_EQ(4U, s.size()); | 730 ASSERT_EQ(4U, s.size()); |
| 720 EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode()); | 731 EXPECT_EQ(kAVXFloat64Add, s[0]->arch_opcode()); |
| 721 EXPECT_EQ(kAVXFloat64Mul, s[1]->arch_opcode()); | 732 EXPECT_EQ(kAVXFloat64Mul, s[1]->arch_opcode()); |
| 722 EXPECT_EQ(kAVXFloat64Sub, s[2]->arch_opcode()); | 733 EXPECT_EQ(kAVXFloat64Sub, s[2]->arch_opcode()); |
| 723 EXPECT_EQ(kAVXFloat64Div, s[3]->arch_opcode()); | 734 EXPECT_EQ(kAVXFloat64Div, s[3]->arch_opcode()); |
| 724 } | 735 } |
| 725 { | 736 { |
| 726 StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64); | 737 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), |
| 738 MachineType::Float64()); |
| 727 Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1)); | 739 Node* add = m.Float64Add(m.Parameter(0), m.Parameter(1)); |
| 728 Node* mul = m.Float64Mul(add, m.Parameter(1)); | 740 Node* mul = m.Float64Mul(add, m.Parameter(1)); |
| 729 Node* sub = m.Float64Sub(mul, add); | 741 Node* sub = m.Float64Sub(mul, add); |
| 730 Node* ret = m.Float64Div(mul, sub); | 742 Node* ret = m.Float64Div(mul, sub); |
| 731 m.Return(ret); | 743 m.Return(ret); |
| 732 Stream s = m.Build(); | 744 Stream s = m.Build(); |
| 733 ASSERT_EQ(4U, s.size()); | 745 ASSERT_EQ(4U, s.size()); |
| 734 EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode()); | 746 EXPECT_EQ(kSSEFloat64Add, s[0]->arch_opcode()); |
| 735 EXPECT_EQ(kSSEFloat64Mul, s[1]->arch_opcode()); | 747 EXPECT_EQ(kSSEFloat64Mul, s[1]->arch_opcode()); |
| 736 EXPECT_EQ(kSSEFloat64Sub, s[2]->arch_opcode()); | 748 EXPECT_EQ(kSSEFloat64Sub, s[2]->arch_opcode()); |
| 737 EXPECT_EQ(kSSEFloat64Div, s[3]->arch_opcode()); | 749 EXPECT_EQ(kSSEFloat64Div, s[3]->arch_opcode()); |
| 738 } | 750 } |
| 739 } | 751 } |
| 740 | 752 |
| 741 | 753 |
| 742 TEST_F(InstructionSelectorTest, Float32SubWithMinusZeroAndParameter) { | 754 TEST_F(InstructionSelectorTest, Float32SubWithMinusZeroAndParameter) { |
| 743 { | 755 { |
| 744 StreamBuilder m(this, kMachFloat32, kMachFloat32); | 756 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); |
| 745 Node* const p0 = m.Parameter(0); | 757 Node* const p0 = m.Parameter(0); |
| 746 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); | 758 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); |
| 747 m.Return(n); | 759 m.Return(n); |
| 748 Stream s = m.Build(); | 760 Stream s = m.Build(); |
| 749 ASSERT_EQ(1U, s.size()); | 761 ASSERT_EQ(1U, s.size()); |
| 750 EXPECT_EQ(kSSEFloat32Neg, s[0]->arch_opcode()); | 762 EXPECT_EQ(kSSEFloat32Neg, s[0]->arch_opcode()); |
| 751 ASSERT_EQ(1U, s[0]->InputCount()); | 763 ASSERT_EQ(1U, s[0]->InputCount()); |
| 752 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 764 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 753 ASSERT_EQ(1U, s[0]->OutputCount()); | 765 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 754 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 766 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 755 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 767 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 756 } | 768 } |
| 757 { | 769 { |
| 758 StreamBuilder m(this, kMachFloat32, kMachFloat32); | 770 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); |
| 759 Node* const p0 = m.Parameter(0); | 771 Node* const p0 = m.Parameter(0); |
| 760 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); | 772 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); |
| 761 m.Return(n); | 773 m.Return(n); |
| 762 Stream s = m.Build(AVX); | 774 Stream s = m.Build(AVX); |
| 763 ASSERT_EQ(1U, s.size()); | 775 ASSERT_EQ(1U, s.size()); |
| 764 EXPECT_EQ(kAVXFloat32Neg, s[0]->arch_opcode()); | 776 EXPECT_EQ(kAVXFloat32Neg, s[0]->arch_opcode()); |
| 765 ASSERT_EQ(1U, s[0]->InputCount()); | 777 ASSERT_EQ(1U, s[0]->InputCount()); |
| 766 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 778 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 767 ASSERT_EQ(1U, s[0]->OutputCount()); | 779 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 768 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 780 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 769 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 781 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 770 } | 782 } |
| 771 } | 783 } |
| 772 | 784 |
| 773 | 785 |
| 774 TEST_F(InstructionSelectorTest, Float64SubWithMinusZeroAndParameter) { | 786 TEST_F(InstructionSelectorTest, Float64SubWithMinusZeroAndParameter) { |
| 775 { | 787 { |
| 776 StreamBuilder m(this, kMachFloat64, kMachFloat64); | 788 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); |
| 777 Node* const p0 = m.Parameter(0); | 789 Node* const p0 = m.Parameter(0); |
| 778 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); | 790 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); |
| 779 m.Return(n); | 791 m.Return(n); |
| 780 Stream s = m.Build(); | 792 Stream s = m.Build(); |
| 781 ASSERT_EQ(1U, s.size()); | 793 ASSERT_EQ(1U, s.size()); |
| 782 EXPECT_EQ(kSSEFloat64Neg, s[0]->arch_opcode()); | 794 EXPECT_EQ(kSSEFloat64Neg, s[0]->arch_opcode()); |
| 783 ASSERT_EQ(1U, s[0]->InputCount()); | 795 ASSERT_EQ(1U, s[0]->InputCount()); |
| 784 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 796 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 785 ASSERT_EQ(1U, s[0]->OutputCount()); | 797 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 786 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 798 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 787 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 799 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 788 } | 800 } |
| 789 { | 801 { |
| 790 StreamBuilder m(this, kMachFloat64, kMachFloat64); | 802 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); |
| 791 Node* const p0 = m.Parameter(0); | 803 Node* const p0 = m.Parameter(0); |
| 792 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); | 804 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); |
| 793 m.Return(n); | 805 m.Return(n); |
| 794 Stream s = m.Build(AVX); | 806 Stream s = m.Build(AVX); |
| 795 ASSERT_EQ(1U, s.size()); | 807 ASSERT_EQ(1U, s.size()); |
| 796 EXPECT_EQ(kAVXFloat64Neg, s[0]->arch_opcode()); | 808 EXPECT_EQ(kAVXFloat64Neg, s[0]->arch_opcode()); |
| 797 ASSERT_EQ(1U, s[0]->InputCount()); | 809 ASSERT_EQ(1U, s[0]->InputCount()); |
| 798 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 810 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 799 ASSERT_EQ(1U, s[0]->OutputCount()); | 811 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 800 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 812 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 801 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); | 813 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 802 } | 814 } |
| 803 } | 815 } |
| 804 | 816 |
| 805 | 817 |
| 806 // ----------------------------------------------------------------------------- | 818 // ----------------------------------------------------------------------------- |
| 807 // Miscellaneous. | 819 // Miscellaneous. |
| 808 | 820 |
| 809 | 821 |
| 810 TEST_F(InstructionSelectorTest, Uint32LessThanWithLoadAndLoadStackPointer) { | 822 TEST_F(InstructionSelectorTest, Uint32LessThanWithLoadAndLoadStackPointer) { |
| 811 StreamBuilder m(this, kMachBool); | 823 StreamBuilder m(this, MachineType::Bool()); |
| 812 Node* const sl = m.Load( | 824 Node* const sl = m.Load( |
| 813 kMachPtr, | 825 MachineType::Pointer(), |
| 814 m.ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); | 826 m.ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); |
| 815 Node* const sp = m.LoadStackPointer(); | 827 Node* const sp = m.LoadStackPointer(); |
| 816 Node* const n = m.Uint32LessThan(sl, sp); | 828 Node* const n = m.Uint32LessThan(sl, sp); |
| 817 m.Return(n); | 829 m.Return(n); |
| 818 Stream s = m.Build(); | 830 Stream s = m.Build(); |
| 819 ASSERT_EQ(1U, s.size()); | 831 ASSERT_EQ(1U, s.size()); |
| 820 EXPECT_EQ(kIA32StackCheck, s[0]->arch_opcode()); | 832 EXPECT_EQ(kIA32StackCheck, s[0]->arch_opcode()); |
| 821 ASSERT_EQ(0U, s[0]->InputCount()); | 833 ASSERT_EQ(0U, s[0]->InputCount()); |
| 822 ASSERT_EQ(1U, s[0]->OutputCount()); | 834 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 823 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 835 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 824 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | 836 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 825 EXPECT_EQ(kUnsignedGreaterThan, s[0]->flags_condition()); | 837 EXPECT_EQ(kUnsignedGreaterThan, s[0]->flags_condition()); |
| 826 } | 838 } |
| 827 | 839 |
| 828 | 840 |
| 829 TEST_F(InstructionSelectorTest, Word32Clz) { | 841 TEST_F(InstructionSelectorTest, Word32Clz) { |
| 830 StreamBuilder m(this, kMachUint32, kMachUint32); | 842 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32()); |
| 831 Node* const p0 = m.Parameter(0); | 843 Node* const p0 = m.Parameter(0); |
| 832 Node* const n = m.Word32Clz(p0); | 844 Node* const n = m.Word32Clz(p0); |
| 833 m.Return(n); | 845 m.Return(n); |
| 834 Stream s = m.Build(); | 846 Stream s = m.Build(); |
| 835 ASSERT_EQ(1U, s.size()); | 847 ASSERT_EQ(1U, s.size()); |
| 836 EXPECT_EQ(kIA32Lzcnt, s[0]->arch_opcode()); | 848 EXPECT_EQ(kIA32Lzcnt, s[0]->arch_opcode()); |
| 837 ASSERT_EQ(1U, s[0]->InputCount()); | 849 ASSERT_EQ(1U, s[0]->InputCount()); |
| 838 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 850 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 839 ASSERT_EQ(1U, s[0]->OutputCount()); | 851 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 840 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 852 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 841 } | 853 } |
| 842 | 854 |
| 843 } // namespace compiler | 855 } // namespace compiler |
| 844 } // namespace internal | 856 } // namespace internal |
| 845 } // namespace v8 | 857 } // namespace v8 |
| OLD | NEW |