| 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 "src/base/adapters.h" | 5 #include "src/base/adapters.h" |
| 6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
| 7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 | 10 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 | 125 |
| 126 | 126 |
| 127 static void VisitBinop(InstructionSelector* selector, Node* node, | 127 static void VisitBinop(InstructionSelector* selector, Node* node, |
| 128 InstructionCode opcode) { | 128 InstructionCode opcode) { |
| 129 FlagsContinuation cont; | 129 FlagsContinuation cont; |
| 130 VisitBinop(selector, node, opcode, &cont); | 130 VisitBinop(selector, node, opcode, &cont); |
| 131 } | 131 } |
| 132 | 132 |
| 133 | 133 |
| 134 void InstructionSelector::VisitLoad(Node* node) { | 134 void InstructionSelector::VisitLoad(Node* node) { |
| 135 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 135 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
| 136 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | |
| 137 Mips64OperandGenerator g(this); | 136 Mips64OperandGenerator g(this); |
| 138 Node* base = node->InputAt(0); | 137 Node* base = node->InputAt(0); |
| 139 Node* index = node->InputAt(1); | 138 Node* index = node->InputAt(1); |
| 140 | 139 |
| 141 ArchOpcode opcode; | 140 ArchOpcode opcode; |
| 142 switch (rep) { | 141 switch (load_rep.representation()) { |
| 143 case kRepFloat32: | 142 case MachineRepresentation::kFloat32: |
| 144 opcode = kMips64Lwc1; | 143 opcode = kMips64Lwc1; |
| 145 break; | 144 break; |
| 146 case kRepFloat64: | 145 case MachineRepresentation::kFloat64: |
| 147 opcode = kMips64Ldc1; | 146 opcode = kMips64Ldc1; |
| 148 break; | 147 break; |
| 149 case kRepBit: // Fall through. | 148 case MachineRepresentation::kBit: // Fall through. |
| 150 case kRepWord8: | 149 case MachineRepresentation::kWord8: |
| 151 opcode = typ == kTypeUint32 ? kMips64Lbu : kMips64Lb; | 150 opcode = load_rep.IsUnsigned() ? kMips64Lbu : kMips64Lb; |
| 152 break; | 151 break; |
| 153 case kRepWord16: | 152 case MachineRepresentation::kWord16: |
| 154 opcode = typ == kTypeUint32 ? kMips64Lhu : kMips64Lh; | 153 opcode = load_rep.IsUnsigned() ? kMips64Lhu : kMips64Lh; |
| 155 break; | 154 break; |
| 156 case kRepWord32: | 155 case MachineRepresentation::kWord32: |
| 157 opcode = kMips64Lw; | 156 opcode = kMips64Lw; |
| 158 break; | 157 break; |
| 159 case kRepTagged: // Fall through. | 158 case MachineRepresentation::kTagged: // Fall through. |
| 160 case kRepWord64: | 159 case MachineRepresentation::kWord64: |
| 161 opcode = kMips64Ld; | 160 opcode = kMips64Ld; |
| 162 break; | 161 break; |
| 163 default: | 162 default: |
| 164 UNREACHABLE(); | 163 UNREACHABLE(); |
| 165 return; | 164 return; |
| 166 } | 165 } |
| 167 | 166 |
| 168 if (g.CanBeImmediate(index, opcode)) { | 167 if (g.CanBeImmediate(index, opcode)) { |
| 169 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 168 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 170 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | 169 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
| 171 } else { | 170 } else { |
| 172 InstructionOperand addr_reg = g.TempRegister(); | 171 InstructionOperand addr_reg = g.TempRegister(); |
| 173 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, | 172 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, |
| 174 g.UseRegister(index), g.UseRegister(base)); | 173 g.UseRegister(index), g.UseRegister(base)); |
| 175 // Emit desired load opcode, using temp addr_reg. | 174 // Emit desired load opcode, using temp addr_reg. |
| 176 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 175 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 177 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); | 176 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); |
| 178 } | 177 } |
| 179 } | 178 } |
| 180 | 179 |
| 181 | 180 |
| 182 void InstructionSelector::VisitStore(Node* node) { | 181 void InstructionSelector::VisitStore(Node* node) { |
| 183 Mips64OperandGenerator g(this); | 182 Mips64OperandGenerator g(this); |
| 184 Node* base = node->InputAt(0); | 183 Node* base = node->InputAt(0); |
| 185 Node* index = node->InputAt(1); | 184 Node* index = node->InputAt(1); |
| 186 Node* value = node->InputAt(2); | 185 Node* value = node->InputAt(2); |
| 187 | 186 |
| 188 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 187 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
| 189 WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind(); | 188 WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind(); |
| 190 MachineType rep = RepresentationOf(store_rep.machine_type()); | 189 MachineRepresentation rep = store_rep.machine_type().representation(); |
| 191 | 190 |
| 192 // TODO(mips): I guess this could be done in a better way. | 191 // TODO(mips): I guess this could be done in a better way. |
| 193 if (write_barrier_kind != kNoWriteBarrier) { | 192 if (write_barrier_kind != kNoWriteBarrier) { |
| 194 DCHECK_EQ(kRepTagged, rep); | 193 DCHECK_EQ(MachineRepresentation::kTagged, rep); |
| 195 InstructionOperand inputs[3]; | 194 InstructionOperand inputs[3]; |
| 196 size_t input_count = 0; | 195 size_t input_count = 0; |
| 197 inputs[input_count++] = g.UseUniqueRegister(base); | 196 inputs[input_count++] = g.UseUniqueRegister(base); |
| 198 inputs[input_count++] = g.UseUniqueRegister(index); | 197 inputs[input_count++] = g.UseUniqueRegister(index); |
| 199 inputs[input_count++] = (write_barrier_kind == kMapWriteBarrier) | 198 inputs[input_count++] = (write_barrier_kind == kMapWriteBarrier) |
| 200 ? g.UseRegister(value) | 199 ? g.UseRegister(value) |
| 201 : g.UseUniqueRegister(value); | 200 : g.UseUniqueRegister(value); |
| 202 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny; | 201 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny; |
| 203 switch (write_barrier_kind) { | 202 switch (write_barrier_kind) { |
| 204 case kNoWriteBarrier: | 203 case kNoWriteBarrier: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 215 break; | 214 break; |
| 216 } | 215 } |
| 217 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; | 216 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; |
| 218 size_t const temp_count = arraysize(temps); | 217 size_t const temp_count = arraysize(temps); |
| 219 InstructionCode code = kArchStoreWithWriteBarrier; | 218 InstructionCode code = kArchStoreWithWriteBarrier; |
| 220 code |= MiscField::encode(static_cast<int>(record_write_mode)); | 219 code |= MiscField::encode(static_cast<int>(record_write_mode)); |
| 221 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); | 220 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); |
| 222 } else { | 221 } else { |
| 223 ArchOpcode opcode; | 222 ArchOpcode opcode; |
| 224 switch (rep) { | 223 switch (rep) { |
| 225 case kRepFloat32: | 224 case MachineRepresentation::kFloat32: |
| 226 opcode = kMips64Swc1; | 225 opcode = kMips64Swc1; |
| 227 break; | 226 break; |
| 228 case kRepFloat64: | 227 case MachineRepresentation::kFloat64: |
| 229 opcode = kMips64Sdc1; | 228 opcode = kMips64Sdc1; |
| 230 break; | 229 break; |
| 231 case kRepBit: // Fall through. | 230 case MachineRepresentation::kBit: // Fall through. |
| 232 case kRepWord8: | 231 case MachineRepresentation::kWord8: |
| 233 opcode = kMips64Sb; | 232 opcode = kMips64Sb; |
| 234 break; | 233 break; |
| 235 case kRepWord16: | 234 case MachineRepresentation::kWord16: |
| 236 opcode = kMips64Sh; | 235 opcode = kMips64Sh; |
| 237 break; | 236 break; |
| 238 case kRepWord32: | 237 case MachineRepresentation::kWord32: |
| 239 opcode = kMips64Sw; | 238 opcode = kMips64Sw; |
| 240 break; | 239 break; |
| 241 case kRepTagged: // Fall through. | 240 case MachineRepresentation::kTagged: // Fall through. |
| 242 case kRepWord64: | 241 case MachineRepresentation::kWord64: |
| 243 opcode = kMips64Sd; | 242 opcode = kMips64Sd; |
| 244 break; | 243 break; |
| 245 default: | 244 default: |
| 246 UNREACHABLE(); | 245 UNREACHABLE(); |
| 247 return; | 246 return; |
| 248 } | 247 } |
| 249 | 248 |
| 250 if (g.CanBeImmediate(index, opcode)) { | 249 if (g.CanBeImmediate(index, opcode)) { |
| 251 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 250 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
| 252 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 251 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
| (...skipping 967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1220 } | 1219 } |
| 1221 } | 1220 } |
| 1222 } | 1221 } |
| 1223 } | 1222 } |
| 1224 | 1223 |
| 1225 | 1224 |
| 1226 bool InstructionSelector::IsTailCallAddressImmediate() { return false; } | 1225 bool InstructionSelector::IsTailCallAddressImmediate() { return false; } |
| 1227 | 1226 |
| 1228 | 1227 |
| 1229 void InstructionSelector::VisitCheckedLoad(Node* node) { | 1228 void InstructionSelector::VisitCheckedLoad(Node* node) { |
| 1230 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 1229 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); |
| 1231 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | |
| 1232 Mips64OperandGenerator g(this); | 1230 Mips64OperandGenerator g(this); |
| 1233 Node* const buffer = node->InputAt(0); | 1231 Node* const buffer = node->InputAt(0); |
| 1234 Node* const offset = node->InputAt(1); | 1232 Node* const offset = node->InputAt(1); |
| 1235 Node* const length = node->InputAt(2); | 1233 Node* const length = node->InputAt(2); |
| 1236 ArchOpcode opcode; | 1234 ArchOpcode opcode; |
| 1237 switch (rep) { | 1235 switch (load_rep.representation()) { |
| 1238 case kRepWord8: | 1236 case MachineRepresentation::kWord8: |
| 1239 opcode = typ == kTypeInt32 ? kCheckedLoadInt8 : kCheckedLoadUint8; | 1237 opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8; |
| 1240 break; | 1238 break; |
| 1241 case kRepWord16: | 1239 case MachineRepresentation::kWord16: |
| 1242 opcode = typ == kTypeInt32 ? kCheckedLoadInt16 : kCheckedLoadUint16; | 1240 opcode = load_rep.IsSigned() ? kCheckedLoadInt16 : kCheckedLoadUint16; |
| 1243 break; | 1241 break; |
| 1244 case kRepWord32: | 1242 case MachineRepresentation::kWord32: |
| 1245 opcode = kCheckedLoadWord32; | 1243 opcode = kCheckedLoadWord32; |
| 1246 break; | 1244 break; |
| 1247 case kRepWord64: | 1245 case MachineRepresentation::kWord64: |
| 1248 opcode = kCheckedLoadWord64; | 1246 opcode = kCheckedLoadWord64; |
| 1249 break; | 1247 break; |
| 1250 case kRepFloat32: | 1248 case MachineRepresentation::kFloat32: |
| 1251 opcode = kCheckedLoadFloat32; | 1249 opcode = kCheckedLoadFloat32; |
| 1252 break; | 1250 break; |
| 1253 case kRepFloat64: | 1251 case MachineRepresentation::kFloat64: |
| 1254 opcode = kCheckedLoadFloat64; | 1252 opcode = kCheckedLoadFloat64; |
| 1255 break; | 1253 break; |
| 1256 default: | 1254 default: |
| 1257 UNREACHABLE(); | 1255 UNREACHABLE(); |
| 1258 return; | 1256 return; |
| 1259 } | 1257 } |
| 1260 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) | 1258 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) |
| 1261 ? g.UseImmediate(offset) | 1259 ? g.UseImmediate(offset) |
| 1262 : g.UseRegister(offset); | 1260 : g.UseRegister(offset); |
| 1263 | 1261 |
| 1264 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) | 1262 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
| 1265 ? g.CanBeImmediate(length, opcode) | 1263 ? g.CanBeImmediate(length, opcode) |
| 1266 ? g.UseImmediate(length) | 1264 ? g.UseImmediate(length) |
| 1267 : g.UseRegister(length) | 1265 : g.UseRegister(length) |
| 1268 : g.UseRegister(length); | 1266 : g.UseRegister(length); |
| 1269 | 1267 |
| 1270 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 1268 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 1271 g.DefineAsRegister(node), offset_operand, length_operand, | 1269 g.DefineAsRegister(node), offset_operand, length_operand, |
| 1272 g.UseRegister(buffer)); | 1270 g.UseRegister(buffer)); |
| 1273 } | 1271 } |
| 1274 | 1272 |
| 1275 | 1273 |
| 1276 void InstructionSelector::VisitCheckedStore(Node* node) { | 1274 void InstructionSelector::VisitCheckedStore(Node* node) { |
| 1277 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 1275 MachineRepresentation rep = |
| 1276 CheckedStoreRepresentationOf(node->op()).representation(); |
| 1278 Mips64OperandGenerator g(this); | 1277 Mips64OperandGenerator g(this); |
| 1279 Node* const buffer = node->InputAt(0); | 1278 Node* const buffer = node->InputAt(0); |
| 1280 Node* const offset = node->InputAt(1); | 1279 Node* const offset = node->InputAt(1); |
| 1281 Node* const length = node->InputAt(2); | 1280 Node* const length = node->InputAt(2); |
| 1282 Node* const value = node->InputAt(3); | 1281 Node* const value = node->InputAt(3); |
| 1283 ArchOpcode opcode; | 1282 ArchOpcode opcode; |
| 1284 switch (rep) { | 1283 switch (rep) { |
| 1285 case kRepWord8: | 1284 case MachineRepresentation::kWord8: |
| 1286 opcode = kCheckedStoreWord8; | 1285 opcode = kCheckedStoreWord8; |
| 1287 break; | 1286 break; |
| 1288 case kRepWord16: | 1287 case MachineRepresentation::kWord16: |
| 1289 opcode = kCheckedStoreWord16; | 1288 opcode = kCheckedStoreWord16; |
| 1290 break; | 1289 break; |
| 1291 case kRepWord32: | 1290 case MachineRepresentation::kWord32: |
| 1292 opcode = kCheckedStoreWord32; | 1291 opcode = kCheckedStoreWord32; |
| 1293 break; | 1292 break; |
| 1294 case kRepWord64: | 1293 case MachineRepresentation::kWord64: |
| 1295 opcode = kCheckedStoreWord64; | 1294 opcode = kCheckedStoreWord64; |
| 1296 break; | 1295 break; |
| 1297 case kRepFloat32: | 1296 case MachineRepresentation::kFloat32: |
| 1298 opcode = kCheckedStoreFloat32; | 1297 opcode = kCheckedStoreFloat32; |
| 1299 break; | 1298 break; |
| 1300 case kRepFloat64: | 1299 case MachineRepresentation::kFloat64: |
| 1301 opcode = kCheckedStoreFloat64; | 1300 opcode = kCheckedStoreFloat64; |
| 1302 break; | 1301 break; |
| 1303 default: | 1302 default: |
| 1304 UNREACHABLE(); | 1303 UNREACHABLE(); |
| 1305 return; | 1304 return; |
| 1306 } | 1305 } |
| 1307 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) | 1306 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) |
| 1308 ? g.UseImmediate(offset) | 1307 ? g.UseImmediate(offset) |
| 1309 : g.UseRegister(offset); | 1308 : g.UseRegister(offset); |
| 1310 | 1309 |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1777 MachineOperatorBuilder::kFloat32RoundUp | | 1776 MachineOperatorBuilder::kFloat32RoundUp | |
| 1778 MachineOperatorBuilder::kFloat64RoundTruncate | | 1777 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1779 MachineOperatorBuilder::kFloat32RoundTruncate | | 1778 MachineOperatorBuilder::kFloat32RoundTruncate | |
| 1780 MachineOperatorBuilder::kFloat64RoundTiesEven | | 1779 MachineOperatorBuilder::kFloat64RoundTiesEven | |
| 1781 MachineOperatorBuilder::kFloat32RoundTiesEven; | 1780 MachineOperatorBuilder::kFloat32RoundTiesEven; |
| 1782 } | 1781 } |
| 1783 | 1782 |
| 1784 } // namespace compiler | 1783 } // namespace compiler |
| 1785 } // namespace internal | 1784 } // namespace internal |
| 1786 } // namespace v8 | 1785 } // namespace v8 |
| OLD | NEW |