| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
| 7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
| 8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
| 9 #include "src/s390/frames-s390.h" | 9 #include "src/s390/frames-s390.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 namespace compiler { | 13 namespace compiler { |
| 14 | 14 |
| 15 enum ImmediateMode { | 15 enum class OperandMode : uint32_t { |
| 16 kShift32Imm, | 16 kNone = 0u, |
| 17 kShift64Imm, | 17 // Immediate mode |
| 18 kInt32Imm, | 18 kShift32Imm = 1u << 0, |
| 19 kInt32Imm_Negate, | 19 kShift64Imm = 1u << 1, |
| 20 kUint32Imm, | 20 kInt32Imm = 1u << 2, |
| 21 kInt20Imm, | 21 kInt32Imm_Negate = 1u << 3, |
| 22 kNoImmediate | 22 kUint32Imm = 1u << 4, |
| 23 kInt20Imm = 1u << 5, |
| 24 // Instr format |
| 25 kAllowRRR = 1u << 7, |
| 26 kAllowRM = 1u << 8, |
| 27 kAllowRI = 1u << 9, |
| 28 kAllowRRI = 1u << 10, |
| 29 kAllowRRM = 1u << 11, |
| 30 // Useful combination |
| 31 kAllowImmediate = kAllowRI | kAllowRRI, |
| 32 kAllowMemoryOperand = kAllowRM | kAllowRRM, |
| 33 kAllowDistinctOps = kAllowRRR | kAllowRRI | kAllowRRM, |
| 34 kBitWiseCommonMode = kAllowRI | kUint32Imm, |
| 35 kArithmeticCommonMode = kAllowRM | kAllowRI |
| 23 }; | 36 }; |
| 24 | 37 |
| 38 typedef base::Flags<OperandMode, uint32_t> OperandModes; |
| 39 DEFINE_OPERATORS_FOR_FLAGS(OperandModes); |
| 40 OperandModes immediateModeMask = |
| 41 OperandMode::kShift32Imm | OperandMode::kShift64Imm | |
| 42 OperandMode::kInt32Imm | OperandMode::kInt32Imm_Negate | |
| 43 OperandMode::kUint32Imm | OperandMode::kInt20Imm; |
| 44 |
| 45 #define BitWiseOperandMode \ |
| 46 ((OperandMode::kBitWiseCommonMode | \ |
| 47 (CpuFeatures::IsSupported(DISTINCT_OPS) \ |
| 48 ? OperandMode::kAllowRRR \ |
| 49 : OperandMode::kBitWiseCommonMode))) |
| 50 #define AddOperandMode \ |
| 51 ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm | \ |
| 52 (CpuFeatures::IsSupported(DISTINCT_OPS) \ |
| 53 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \ |
| 54 : OperandMode::kArithmeticCommonMode))) |
| 55 #define SubOperandMode \ |
| 56 ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm_Negate | \ |
| 57 (CpuFeatures::IsSupported(DISTINCT_OPS) \ |
| 58 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \ |
| 59 : OperandMode::kArithmeticCommonMode))) |
| 60 #define MulOperandMode \ |
| 61 (OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm) |
| 62 |
| 25 // Adds S390-specific methods for generating operands. | 63 // Adds S390-specific methods for generating operands. |
| 26 class S390OperandGenerator final : public OperandGenerator { | 64 class S390OperandGenerator final : public OperandGenerator { |
| 27 public: | 65 public: |
| 28 explicit S390OperandGenerator(InstructionSelector* selector) | 66 explicit S390OperandGenerator(InstructionSelector* selector) |
| 29 : OperandGenerator(selector) {} | 67 : OperandGenerator(selector) {} |
| 30 | 68 |
| 31 InstructionOperand UseOperand(Node* node, ImmediateMode mode) { | 69 InstructionOperand UseOperand(Node* node, OperandModes mode) { |
| 32 if (CanBeImmediate(node, mode)) { | 70 if (CanBeImmediate(node, mode)) { |
| 33 return UseImmediate(node); | 71 return UseImmediate(node); |
| 34 } | 72 } |
| 35 return UseRegister(node); | 73 return UseRegister(node); |
| 36 } | 74 } |
| 37 | 75 |
| 38 int64_t GetImmediate(Node* node) { | 76 int64_t GetImmediate(Node* node) { |
| 39 if (node->opcode() == IrOpcode::kInt32Constant) | 77 if (node->opcode() == IrOpcode::kInt32Constant) |
| 40 return OpParameter<int32_t>(node); | 78 return OpParameter<int32_t>(node); |
| 41 else if (node->opcode() == IrOpcode::kInt64Constant) | 79 else if (node->opcode() == IrOpcode::kInt64Constant) |
| 42 return OpParameter<int64_t>(node); | 80 return OpParameter<int64_t>(node); |
| 43 else | 81 else |
| 44 UNIMPLEMENTED(); | 82 UNIMPLEMENTED(); |
| 45 return 0L; | 83 return 0L; |
| 46 } | 84 } |
| 47 | 85 |
| 48 bool CanBeImmediate(Node* node, ImmediateMode mode) { | 86 bool CanBeImmediate(Node* node, OperandModes mode) { |
| 49 int64_t value; | 87 int64_t value; |
| 50 if (node->opcode() == IrOpcode::kInt32Constant) | 88 if (node->opcode() == IrOpcode::kInt32Constant) |
| 51 value = OpParameter<int32_t>(node); | 89 value = OpParameter<int32_t>(node); |
| 52 else if (node->opcode() == IrOpcode::kInt64Constant) | 90 else if (node->opcode() == IrOpcode::kInt64Constant) |
| 53 value = OpParameter<int64_t>(node); | 91 value = OpParameter<int64_t>(node); |
| 54 else | 92 else |
| 55 return false; | 93 return false; |
| 56 return CanBeImmediate(value, mode); | 94 return CanBeImmediate(value, mode); |
| 57 } | 95 } |
| 58 | 96 |
| 59 bool CanBeImmediate(int64_t value, ImmediateMode mode) { | 97 bool CanBeImmediate(int64_t value, OperandModes mode) { |
| 60 switch (mode) { | 98 if (mode & OperandMode::kShift32Imm) |
| 61 case kShift32Imm: | 99 return 0 <= value && value < 32; |
| 62 return 0 <= value && value < 32; | 100 else if (mode & OperandMode::kShift64Imm) |
| 63 case kShift64Imm: | 101 return 0 <= value && value < 64; |
| 64 return 0 <= value && value < 64; | 102 else if (mode & OperandMode::kInt32Imm) |
| 65 case kInt32Imm: | 103 return is_int32(value); |
| 66 return is_int32(value); | 104 else if (mode & OperandMode::kInt32Imm_Negate) |
| 67 case kInt32Imm_Negate: | 105 return is_int32(-value); |
| 68 return is_int32(-value); | 106 else if (mode & OperandMode::kUint32Imm) |
| 69 case kUint32Imm: | 107 return is_uint32(value); |
| 70 return is_uint32(value); | 108 else if (mode & OperandMode::kInt20Imm) |
| 71 case kInt20Imm: | 109 return is_int20(value); |
| 72 return is_int20(value); | 110 else |
| 73 case kNoImmediate: | 111 return false; |
| 74 return false; | |
| 75 } | |
| 76 return false; | |
| 77 } | 112 } |
| 78 | 113 |
| 79 AddressingMode GenerateMemoryOperandInputs(Node* index, Node* base, | 114 AddressingMode GenerateMemoryOperandInputs(Node* index, Node* base, |
| 80 Node* displacement, | 115 Node* displacement, |
| 81 DisplacementMode displacement_mode, | 116 DisplacementMode displacement_mode, |
| 82 InstructionOperand inputs[], | 117 InstructionOperand inputs[], |
| 83 size_t* input_count) { | 118 size_t* input_count) { |
| 84 AddressingMode mode = kMode_MRI; | 119 AddressingMode mode = kMode_MRI; |
| 85 if (base != nullptr) { | 120 if (base != nullptr) { |
| 86 inputs[(*input_count)++] = UseRegister(base); | 121 inputs[(*input_count)++] = UseRegister(base); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 size_t* input_count) { | 159 size_t* input_count) { |
| 125 #if V8_TARGET_ARCH_S390X | 160 #if V8_TARGET_ARCH_S390X |
| 126 BaseWithIndexAndDisplacement64Matcher m(operand, | 161 BaseWithIndexAndDisplacement64Matcher m(operand, |
| 127 AddressOption::kAllowInputSwap); | 162 AddressOption::kAllowInputSwap); |
| 128 #else | 163 #else |
| 129 BaseWithIndexAndDisplacement32Matcher m(operand, | 164 BaseWithIndexAndDisplacement32Matcher m(operand, |
| 130 AddressOption::kAllowInputSwap); | 165 AddressOption::kAllowInputSwap); |
| 131 #endif | 166 #endif |
| 132 DCHECK(m.matches()); | 167 DCHECK(m.matches()); |
| 133 if ((m.displacement() == nullptr || | 168 if ((m.displacement() == nullptr || |
| 134 CanBeImmediate(m.displacement(), kInt20Imm))) { | 169 CanBeImmediate(m.displacement(), OperandMode::kInt20Imm))) { |
| 135 DCHECK(m.scale() == 0); | 170 DCHECK(m.scale() == 0); |
| 136 return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), | 171 return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), |
| 137 m.displacement_mode(), inputs, | 172 m.displacement_mode(), inputs, |
| 138 input_count); | 173 input_count); |
| 139 } else { | 174 } else { |
| 140 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); | 175 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); |
| 141 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); | 176 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); |
| 142 return kMode_MRR; | 177 return kMode_MRR; |
| 143 } | 178 } |
| 144 } | 179 } |
| 145 | 180 |
| 146 bool CanBeBetterLeftOperand(Node* node) const { | 181 bool CanBeBetterLeftOperand(Node* node) const { |
| 147 return !selector()->IsLive(node); | 182 return !selector()->IsLive(node); |
| 148 } | 183 } |
| 149 | 184 |
| 150 MachineRepresentation GetRepresentation(Node* node) { | 185 MachineRepresentation GetRepresentation(Node* node) { |
| 151 return sequence()->GetRepresentation(selector()->GetVirtualRegister(node)); | 186 return sequence()->GetRepresentation(selector()->GetVirtualRegister(node)); |
| 152 } | 187 } |
| 153 | 188 |
| 154 bool Is64BitOperand(Node* node) { | 189 bool Is64BitOperand(Node* node) { |
| 155 return MachineRepresentation::kWord64 == GetRepresentation(node); | 190 return MachineRepresentation::kWord64 == GetRepresentation(node); |
| 156 } | 191 } |
| 157 }; | 192 }; |
| 158 | 193 |
| 159 namespace { | 194 namespace { |
| 160 | 195 |
| 196 ArchOpcode SelectLoadOpcode(Node* node) { |
| 197 NodeMatcher m(node); |
| 198 DCHECK(m.IsLoad()); |
| 199 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
| 200 ArchOpcode opcode = kArchNop; |
| 201 switch (load_rep.representation()) { |
| 202 case MachineRepresentation::kFloat32: |
| 203 opcode = kS390_LoadFloat32; |
| 204 break; |
| 205 case MachineRepresentation::kFloat64: |
| 206 opcode = kS390_LoadDouble; |
| 207 break; |
| 208 case MachineRepresentation::kBit: // Fall through. |
| 209 case MachineRepresentation::kWord8: |
| 210 opcode = load_rep.IsSigned() ? kS390_LoadWordS8 : kS390_LoadWordU8; |
| 211 break; |
| 212 case MachineRepresentation::kWord16: |
| 213 opcode = load_rep.IsSigned() ? kS390_LoadWordS16 : kS390_LoadWordU16; |
| 214 break; |
| 215 #if !V8_TARGET_ARCH_S390X |
| 216 case MachineRepresentation::kTaggedSigned: // Fall through. |
| 217 case MachineRepresentation::kTaggedPointer: // Fall through. |
| 218 case MachineRepresentation::kTagged: // Fall through. |
| 219 #endif |
| 220 case MachineRepresentation::kWord32: |
| 221 opcode = kS390_LoadWordU32; |
| 222 break; |
| 223 #if V8_TARGET_ARCH_S390X |
| 224 case MachineRepresentation::kTaggedSigned: // Fall through. |
| 225 case MachineRepresentation::kTaggedPointer: // Fall through. |
| 226 case MachineRepresentation::kTagged: // Fall through. |
| 227 case MachineRepresentation::kWord64: |
| 228 opcode = kS390_LoadWord64; |
| 229 break; |
| 230 #else |
| 231 case MachineRepresentation::kWord64: // Fall through. |
| 232 #endif |
| 233 case MachineRepresentation::kSimd128: // Fall through. |
| 234 case MachineRepresentation::kNone: |
| 235 default: |
| 236 UNREACHABLE(); |
| 237 } |
| 238 return opcode; |
| 239 } |
| 240 |
| 241 bool AutoZeroExtendsWord32ToWord64(Node* node) { |
| 242 #if !V8_TARGET_ARCH_S390X |
| 243 return true; |
| 244 #else |
| 245 switch (node->opcode()) { |
| 246 case IrOpcode::kInt32Div: |
| 247 case IrOpcode::kUint32Div: |
| 248 case IrOpcode::kInt32MulHigh: |
| 249 case IrOpcode::kInt32Mod: |
| 250 case IrOpcode::kUint32Mod: |
| 251 return true; |
| 252 default: |
| 253 return false; |
| 254 } |
| 255 return false; |
| 256 #endif |
| 257 } |
| 258 |
| 259 bool ZeroExtendsWord32ToWord64(Node* node) { |
| 260 #if !V8_TARGET_ARCH_S390X |
| 261 return true; |
| 262 #else |
| 263 switch (node->opcode()) { |
| 264 case IrOpcode::kInt32Add: |
| 265 case IrOpcode::kInt32Sub: |
| 266 case IrOpcode::kWord32And: |
| 267 case IrOpcode::kWord32Or: |
| 268 case IrOpcode::kWord32Xor: |
| 269 case IrOpcode::kWord32Shl: |
| 270 case IrOpcode::kWord32Shr: |
| 271 case IrOpcode::kWord32Sar: |
| 272 case IrOpcode::kInt32Mul: |
| 273 case IrOpcode::kWord32Ror: |
| 274 case IrOpcode::kInt32Div: |
| 275 case IrOpcode::kUint32Div: |
| 276 case IrOpcode::kInt32MulHigh: |
| 277 case IrOpcode::kInt32Mod: |
| 278 case IrOpcode::kUint32Mod: |
| 279 return true; |
| 280 // TODO(john.yan): consider the following case to be valid |
| 281 // case IrOpcode::kWord32Equal: |
| 282 // case IrOpcode::kInt32LessThan: |
| 283 // case IrOpcode::kInt32LessThanOrEqual: |
| 284 // case IrOpcode::kUint32LessThan: |
| 285 // case IrOpcode::kUint32LessThanOrEqual: |
| 286 // case IrOpcode::kUint32MulHigh: |
| 287 // // These 32-bit operations implicitly zero-extend to 64-bit on x64, so |
| 288 // the |
| 289 // // zero-extension is a no-op. |
| 290 // return true; |
| 291 // case IrOpcode::kProjection: { |
| 292 // Node* const value = node->InputAt(0); |
| 293 // switch (value->opcode()) { |
| 294 // case IrOpcode::kInt32AddWithOverflow: |
| 295 // case IrOpcode::kInt32SubWithOverflow: |
| 296 // case IrOpcode::kInt32MulWithOverflow: |
| 297 // return true; |
| 298 // default: |
| 299 // return false; |
| 300 // } |
| 301 // } |
| 302 case IrOpcode::kLoad: { |
| 303 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
| 304 switch (load_rep.representation()) { |
| 305 case MachineRepresentation::kWord32: |
| 306 return true; |
| 307 default: |
| 308 return false; |
| 309 } |
| 310 } |
| 311 default: |
| 312 return false; |
| 313 } |
| 314 #endif |
| 315 } |
| 316 |
| 161 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { | 317 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { |
| 162 S390OperandGenerator g(selector); | 318 S390OperandGenerator g(selector); |
| 163 selector->Emit(opcode, g.DefineAsRegister(node), | 319 selector->Emit(opcode, g.DefineAsRegister(node), |
| 164 g.UseRegister(node->InputAt(0))); | 320 g.UseRegister(node->InputAt(0))); |
| 165 } | 321 } |
| 166 | 322 |
| 167 void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { | 323 void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { |
| 168 S390OperandGenerator g(selector); | 324 S390OperandGenerator g(selector); |
| 169 selector->Emit(opcode, g.DefineAsRegister(node), | 325 selector->Emit(opcode, g.DefineAsRegister(node), |
| 170 g.UseRegister(node->InputAt(0)), | 326 g.UseRegister(node->InputAt(0)), |
| 171 g.UseRegister(node->InputAt(1))); | 327 g.UseRegister(node->InputAt(1))); |
| 172 } | 328 } |
| 173 | 329 |
| 330 #if V8_TARGET_ARCH_S390X |
| 174 void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, | 331 void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, |
| 175 ImmediateMode operand_mode) { | 332 OperandModes operand_mode) { |
| 176 S390OperandGenerator g(selector); | 333 S390OperandGenerator g(selector); |
| 177 selector->Emit(opcode, g.DefineAsRegister(node), | 334 selector->Emit(opcode, g.DefineAsRegister(node), |
| 178 g.UseRegister(node->InputAt(0)), | 335 g.UseRegister(node->InputAt(0)), |
| 179 g.UseOperand(node->InputAt(1), operand_mode)); | 336 g.UseOperand(node->InputAt(1), operand_mode)); |
| 180 } | 337 } |
| 181 | 338 |
| 182 #if V8_TARGET_ARCH_S390X | |
| 183 void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode, | 339 void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode, |
| 184 Node* node) { | 340 Node* node) { |
| 185 S390OperandGenerator g(selector); | 341 S390OperandGenerator g(selector); |
| 186 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))}; | 342 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))}; |
| 187 InstructionOperand outputs[2]; | 343 InstructionOperand outputs[2]; |
| 188 size_t output_count = 0; | 344 size_t output_count = 0; |
| 189 outputs[output_count++] = g.DefineAsRegister(node); | 345 outputs[output_count++] = g.DefineAsRegister(node); |
| 190 | 346 |
| 191 Node* success_output = NodeProperties::FindProjection(node, 1); | 347 Node* success_output = NodeProperties::FindProjection(node, 1); |
| 192 if (success_output) { | 348 if (success_output) { |
| 193 outputs[output_count++] = g.DefineAsRegister(success_output); | 349 outputs[output_count++] = g.DefineAsRegister(success_output); |
| 194 } | 350 } |
| 195 | 351 |
| 196 selector->Emit(opcode, output_count, outputs, 1, inputs); | 352 selector->Emit(opcode, output_count, outputs, 1, inputs); |
| 197 } | 353 } |
| 198 #endif | 354 #endif |
| 199 | 355 |
| 200 // Shared routine for multiple binary operations. | 356 // Shared routine for multiple binary operations. |
| 201 template <typename Matcher> | 357 template <typename Matcher> |
| 202 void VisitBinop(InstructionSelector* selector, Node* node, | 358 void VisitBinop(InstructionSelector* selector, Node* node, |
| 203 InstructionCode opcode, ImmediateMode operand_mode, | 359 InstructionCode opcode, OperandModes operand_mode, |
| 204 FlagsContinuation* cont) { | 360 FlagsContinuation* cont) { |
| 205 S390OperandGenerator g(selector); | 361 S390OperandGenerator g(selector); |
| 206 Matcher m(node); | 362 Matcher m(node); |
| 207 Node* left = m.left().node(); | 363 Node* left = m.left().node(); |
| 208 Node* right = m.right().node(); | 364 Node* right = m.right().node(); |
| 209 InstructionOperand inputs[4]; | 365 InstructionOperand inputs[4]; |
| 210 size_t input_count = 0; | 366 size_t input_count = 0; |
| 211 InstructionOperand outputs[2]; | 367 InstructionOperand outputs[2]; |
| 212 size_t output_count = 0; | 368 size_t output_count = 0; |
| 213 | 369 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, | 418 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 263 cont->reason(), cont->frame_state()); | 419 cont->reason(), cont->frame_state()); |
| 264 } else { | 420 } else { |
| 265 selector->Emit(opcode, output_count, outputs, input_count, inputs); | 421 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 266 } | 422 } |
| 267 } | 423 } |
| 268 | 424 |
| 269 // Shared routine for multiple binary operations. | 425 // Shared routine for multiple binary operations. |
| 270 template <typename Matcher> | 426 template <typename Matcher> |
| 271 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, | 427 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
| 272 ImmediateMode operand_mode) { | 428 OperandModes operand_mode) { |
| 273 FlagsContinuation cont; | 429 FlagsContinuation cont; |
| 274 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); | 430 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); |
| 275 } | 431 } |
| 276 | 432 |
| 433 void VisitBin32op(InstructionSelector* selector, Node* node, |
| 434 InstructionCode opcode, OperandModes operand_mode, |
| 435 FlagsContinuation* cont) { |
| 436 S390OperandGenerator g(selector); |
| 437 Int32BinopMatcher m(node); |
| 438 Node* left = m.left().node(); |
| 439 Node* right = m.right().node(); |
| 440 InstructionOperand inputs[8]; |
| 441 size_t input_count = 0; |
| 442 InstructionOperand outputs[2]; |
| 443 size_t output_count = 0; |
| 444 |
| 445 // match left of TruncateInt64ToInt32 |
| 446 if (m.left().IsTruncateInt64ToInt32() && selector->CanCover(node, left)) { |
| 447 left = left->InputAt(0); |
| 448 } |
| 449 // match right of TruncateInt64ToInt32 |
| 450 if (m.right().IsTruncateInt64ToInt32() && selector->CanCover(node, right)) { |
| 451 right = right->InputAt(0); |
| 452 } |
| 453 |
| 454 #if V8_TARGET_ARCH_S390X |
| 455 if ((ZeroExtendsWord32ToWord64(right) || g.CanBeBetterLeftOperand(right)) && |
| 456 node->op()->HasProperty(Operator::kCommutative) && |
| 457 !g.CanBeImmediate(right, operand_mode)) { |
| 458 std::swap(left, right); |
| 459 } |
| 460 #else |
| 461 if (node->op()->HasProperty(Operator::kCommutative) && |
| 462 !g.CanBeImmediate(right, operand_mode) && |
| 463 (g.CanBeBetterLeftOperand(right))) { |
| 464 std::swap(left, right); |
| 465 } |
| 466 #endif |
| 467 |
| 468 // left is always register |
| 469 InstructionOperand const left_input = g.UseRegister(left); |
| 470 inputs[input_count++] = left_input; |
| 471 |
| 472 // TODO(turbofan): match complex addressing modes. |
| 473 if (left == right) { |
| 474 // If both inputs refer to the same operand, enforce allocating a register |
| 475 // for both of them to ensure that we don't end up generating code like |
| 476 // this: |
| 477 // |
| 478 // mov rax, [rbp-0x10] |
| 479 // add rax, [rbp-0x10] |
| 480 // jo label |
| 481 inputs[input_count++] = left_input; |
| 482 // Can only be RR or RRR |
| 483 operand_mode &= OperandMode::kAllowRRR; |
| 484 } else if ((operand_mode & OperandMode::kAllowImmediate) && |
| 485 g.CanBeImmediate(right, operand_mode)) { |
| 486 inputs[input_count++] = g.UseImmediate(right); |
| 487 // Can only be RI or RRI |
| 488 operand_mode &= OperandMode::kAllowImmediate; |
| 489 } else if (operand_mode & OperandMode::kAllowMemoryOperand) { |
| 490 NodeMatcher mright(right); |
| 491 if (mright.IsLoad() && selector->CanCover(node, right) && |
| 492 SelectLoadOpcode(right) == kS390_LoadWordU32) { |
| 493 AddressingMode mode = |
| 494 g.GetEffectiveAddressMemoryOperand(right, inputs, &input_count); |
| 495 opcode |= AddressingModeField::encode(mode); |
| 496 operand_mode &= ~OperandMode::kAllowImmediate; |
| 497 if (operand_mode & OperandMode::kAllowRM) |
| 498 operand_mode &= ~OperandMode::kAllowDistinctOps; |
| 499 } else if (operand_mode & OperandMode::kAllowRM) { |
| 500 DCHECK(!(operand_mode & OperandMode::kAllowRRM)); |
| 501 inputs[input_count++] = g.Use(right); |
| 502 // Can not be Immediate |
| 503 operand_mode &= |
| 504 ~OperandMode::kAllowImmediate & ~OperandMode::kAllowDistinctOps; |
| 505 } else if (operand_mode & OperandMode::kAllowRRM) { |
| 506 DCHECK(!(operand_mode & OperandMode::kAllowRM)); |
| 507 inputs[input_count++] = g.Use(right); |
| 508 // Can not be Immediate |
| 509 operand_mode &= ~OperandMode::kAllowImmediate; |
| 510 } else { |
| 511 UNREACHABLE(); |
| 512 } |
| 513 } else { |
| 514 inputs[input_count++] = g.UseRegister(right); |
| 515 // Can only be RR or RRR |
| 516 operand_mode &= OperandMode::kAllowRRR; |
| 517 } |
| 518 |
| 519 bool doZeroExt = |
| 520 AutoZeroExtendsWord32ToWord64(node) || !ZeroExtendsWord32ToWord64(left); |
| 521 |
| 522 inputs[input_count++] = |
| 523 g.TempImmediate(doZeroExt && (!AutoZeroExtendsWord32ToWord64(node))); |
| 524 |
| 525 if (cont->IsBranch()) { |
| 526 inputs[input_count++] = g.Label(cont->true_block()); |
| 527 inputs[input_count++] = g.Label(cont->false_block()); |
| 528 } |
| 529 |
| 530 if (doZeroExt && (operand_mode & OperandMode::kAllowDistinctOps) && |
| 531 // If we can deoptimize as a result of the binop, we need to make sure |
| 532 // that |
| 533 // the deopt inputs are not overwritten by the binop result. One way |
| 534 // to achieve that is to declare the output register as same-as-first. |
| 535 !cont->IsDeoptimize()) { |
| 536 outputs[output_count++] = g.DefineAsRegister(node); |
| 537 } else { |
| 538 outputs[output_count++] = g.DefineSameAsFirst(node); |
| 539 } |
| 540 |
| 541 if (cont->IsSet()) { |
| 542 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| 543 } |
| 544 |
| 545 DCHECK_NE(0u, input_count); |
| 546 DCHECK_NE(0u, output_count); |
| 547 DCHECK_GE(arraysize(inputs), input_count); |
| 548 DCHECK_GE(arraysize(outputs), output_count); |
| 549 |
| 550 opcode = cont->Encode(opcode); |
| 551 |
| 552 if (cont->IsDeoptimize()) { |
| 553 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 554 cont->reason(), cont->frame_state()); |
| 555 } else { |
| 556 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 557 } |
| 558 } |
| 559 |
| 560 void VisitBin32op(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
| 561 OperandModes operand_mode) { |
| 562 FlagsContinuation cont; |
| 563 VisitBin32op(selector, node, opcode, operand_mode, &cont); |
| 564 } |
| 565 |
| 277 } // namespace | 566 } // namespace |
| 278 | 567 |
| 279 void InstructionSelector::VisitLoad(Node* node) { | 568 void InstructionSelector::VisitLoad(Node* node) { |
| 280 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); | |
| 281 S390OperandGenerator g(this); | 569 S390OperandGenerator g(this); |
| 282 ArchOpcode opcode = kArchNop; | 570 ArchOpcode opcode = SelectLoadOpcode(node); |
| 283 switch (load_rep.representation()) { | |
| 284 case MachineRepresentation::kFloat32: | |
| 285 opcode = kS390_LoadFloat32; | |
| 286 break; | |
| 287 case MachineRepresentation::kFloat64: | |
| 288 opcode = kS390_LoadDouble; | |
| 289 break; | |
| 290 case MachineRepresentation::kBit: // Fall through. | |
| 291 case MachineRepresentation::kWord8: | |
| 292 opcode = load_rep.IsSigned() ? kS390_LoadWordS8 : kS390_LoadWordU8; | |
| 293 break; | |
| 294 case MachineRepresentation::kWord16: | |
| 295 opcode = load_rep.IsSigned() ? kS390_LoadWordS16 : kS390_LoadWordU16; | |
| 296 break; | |
| 297 #if !V8_TARGET_ARCH_S390X | |
| 298 case MachineRepresentation::kTaggedSigned: // Fall through. | |
| 299 case MachineRepresentation::kTaggedPointer: // Fall through. | |
| 300 case MachineRepresentation::kTagged: // Fall through. | |
| 301 #endif | |
| 302 case MachineRepresentation::kWord32: | |
| 303 opcode = kS390_LoadWordU32; | |
| 304 break; | |
| 305 #if V8_TARGET_ARCH_S390X | |
| 306 case MachineRepresentation::kTaggedSigned: // Fall through. | |
| 307 case MachineRepresentation::kTaggedPointer: // Fall through. | |
| 308 case MachineRepresentation::kTagged: // Fall through. | |
| 309 case MachineRepresentation::kWord64: | |
| 310 opcode = kS390_LoadWord64; | |
| 311 break; | |
| 312 #else | |
| 313 case MachineRepresentation::kWord64: // Fall through. | |
| 314 #endif | |
| 315 case MachineRepresentation::kSimd128: // Fall through. | |
| 316 case MachineRepresentation::kNone: | |
| 317 UNREACHABLE(); | |
| 318 return; | |
| 319 } | |
| 320 InstructionOperand outputs[1]; | 571 InstructionOperand outputs[1]; |
| 321 outputs[0] = g.DefineAsRegister(node); | 572 outputs[0] = g.DefineAsRegister(node); |
| 322 InstructionOperand inputs[3]; | 573 InstructionOperand inputs[3]; |
| 323 size_t input_count = 0; | 574 size_t input_count = 0; |
| 324 AddressingMode mode = | 575 AddressingMode mode = |
| 325 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); | 576 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
| 326 InstructionCode code = opcode | AddressingModeField::encode(mode); | 577 InstructionCode code = opcode | AddressingModeField::encode(mode); |
| 327 Emit(code, 1, outputs, input_count, inputs); | 578 Emit(code, 1, outputs, input_count, inputs); |
| 328 } | 579 } |
| 329 | 580 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 343 MachineRepresentation rep = store_rep.representation(); | 594 MachineRepresentation rep = store_rep.representation(); |
| 344 | 595 |
| 345 if (write_barrier_kind != kNoWriteBarrier) { | 596 if (write_barrier_kind != kNoWriteBarrier) { |
| 346 DCHECK_EQ(MachineRepresentation::kTagged, rep); | 597 DCHECK_EQ(MachineRepresentation::kTagged, rep); |
| 347 AddressingMode addressing_mode; | 598 AddressingMode addressing_mode; |
| 348 InstructionOperand inputs[3]; | 599 InstructionOperand inputs[3]; |
| 349 size_t input_count = 0; | 600 size_t input_count = 0; |
| 350 inputs[input_count++] = g.UseUniqueRegister(base); | 601 inputs[input_count++] = g.UseUniqueRegister(base); |
| 351 // OutOfLineRecordWrite uses the offset in an 'AddP' instruction as well as | 602 // OutOfLineRecordWrite uses the offset in an 'AddP' instruction as well as |
| 352 // for the store itself, so we must check compatibility with both. | 603 // for the store itself, so we must check compatibility with both. |
| 353 if (g.CanBeImmediate(offset, kInt20Imm)) { | 604 if (g.CanBeImmediate(offset, OperandMode::kInt20Imm)) { |
| 354 inputs[input_count++] = g.UseImmediate(offset); | 605 inputs[input_count++] = g.UseImmediate(offset); |
| 355 addressing_mode = kMode_MRI; | 606 addressing_mode = kMode_MRI; |
| 356 } else { | 607 } else { |
| 357 inputs[input_count++] = g.UseUniqueRegister(offset); | 608 inputs[input_count++] = g.UseUniqueRegister(offset); |
| 358 addressing_mode = kMode_MRR; | 609 addressing_mode = kMode_MRR; |
| 359 } | 610 } |
| 360 inputs[input_count++] = g.UseUniqueRegister(value); | 611 inputs[input_count++] = g.UseUniqueRegister(value); |
| 361 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny; | 612 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny; |
| 362 switch (write_barrier_kind) { | 613 switch (write_barrier_kind) { |
| 363 case kNoWriteBarrier: | 614 case kNoWriteBarrier: |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 case MachineRepresentation::kWord64: // Fall through. | 738 case MachineRepresentation::kWord64: // Fall through. |
| 488 #endif | 739 #endif |
| 489 case MachineRepresentation::kSimd128: // Fall through. | 740 case MachineRepresentation::kSimd128: // Fall through. |
| 490 case MachineRepresentation::kNone: | 741 case MachineRepresentation::kNone: |
| 491 UNREACHABLE(); | 742 UNREACHABLE(); |
| 492 return; | 743 return; |
| 493 } | 744 } |
| 494 AddressingMode addressingMode = kMode_MRR; | 745 AddressingMode addressingMode = kMode_MRR; |
| 495 Emit(opcode | AddressingModeField::encode(addressingMode), | 746 Emit(opcode | AddressingModeField::encode(addressingMode), |
| 496 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(offset), | 747 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(offset), |
| 497 g.UseOperand(length, kUint32Imm)); | 748 g.UseOperand(length, OperandMode::kUint32Imm)); |
| 498 } | 749 } |
| 499 | 750 |
| 500 void InstructionSelector::VisitCheckedStore(Node* node) { | 751 void InstructionSelector::VisitCheckedStore(Node* node) { |
| 501 MachineRepresentation rep = CheckedStoreRepresentationOf(node->op()); | 752 MachineRepresentation rep = CheckedStoreRepresentationOf(node->op()); |
| 502 S390OperandGenerator g(this); | 753 S390OperandGenerator g(this); |
| 503 Node* const base = node->InputAt(0); | 754 Node* const base = node->InputAt(0); |
| 504 Node* const offset = node->InputAt(1); | 755 Node* const offset = node->InputAt(1); |
| 505 Node* const length = node->InputAt(2); | 756 Node* const length = node->InputAt(2); |
| 506 Node* const value = node->InputAt(3); | 757 Node* const value = node->InputAt(3); |
| 507 ArchOpcode opcode = kArchNop; | 758 ArchOpcode opcode = kArchNop; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 534 case MachineRepresentation::kWord64: // Fall through. | 785 case MachineRepresentation::kWord64: // Fall through. |
| 535 #endif | 786 #endif |
| 536 case MachineRepresentation::kSimd128: // Fall through. | 787 case MachineRepresentation::kSimd128: // Fall through. |
| 537 case MachineRepresentation::kNone: | 788 case MachineRepresentation::kNone: |
| 538 UNREACHABLE(); | 789 UNREACHABLE(); |
| 539 return; | 790 return; |
| 540 } | 791 } |
| 541 AddressingMode addressingMode = kMode_MRR; | 792 AddressingMode addressingMode = kMode_MRR; |
| 542 Emit(opcode | AddressingModeField::encode(addressingMode), g.NoOutput(), | 793 Emit(opcode | AddressingModeField::encode(addressingMode), g.NoOutput(), |
| 543 g.UseRegister(base), g.UseRegister(offset), | 794 g.UseRegister(base), g.UseRegister(offset), |
| 544 g.UseOperand(length, kUint32Imm), g.UseRegister(value)); | 795 g.UseOperand(length, OperandMode::kUint32Imm), g.UseRegister(value)); |
| 545 } | 796 } |
| 546 | 797 |
| 547 #if 0 | 798 #if 0 |
| 548 static inline bool IsContiguousMask32(uint32_t value, int* mb, int* me) { | 799 static inline bool IsContiguousMask32(uint32_t value, int* mb, int* me) { |
| 549 int mask_width = base::bits::CountPopulation32(value); | 800 int mask_width = base::bits::CountPopulation32(value); |
| 550 int mask_msb = base::bits::CountLeadingZeros32(value); | 801 int mask_msb = base::bits::CountLeadingZeros32(value); |
| 551 int mask_lsb = base::bits::CountTrailingZeros32(value); | 802 int mask_lsb = base::bits::CountTrailingZeros32(value); |
| 552 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 32)) | 803 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 32)) |
| 553 return false; | 804 return false; |
| 554 *mb = mask_lsb + mask_width - 1; | 805 *mb = mask_lsb + mask_width - 1; |
| 555 *me = mask_lsb; | 806 *me = mask_lsb; |
| 556 return true; | 807 return true; |
| 557 } | 808 } |
| 558 #endif | 809 #endif |
| 559 | 810 |
| 560 #if V8_TARGET_ARCH_S390X | 811 #if V8_TARGET_ARCH_S390X |
| 561 static inline bool IsContiguousMask64(uint64_t value, int* mb, int* me) { | 812 static inline bool IsContiguousMask64(uint64_t value, int* mb, int* me) { |
| 562 int mask_width = base::bits::CountPopulation64(value); | 813 int mask_width = base::bits::CountPopulation64(value); |
| 563 int mask_msb = base::bits::CountLeadingZeros64(value); | 814 int mask_msb = base::bits::CountLeadingZeros64(value); |
| 564 int mask_lsb = base::bits::CountTrailingZeros64(value); | 815 int mask_lsb = base::bits::CountTrailingZeros64(value); |
| 565 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64)) | 816 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64)) |
| 566 return false; | 817 return false; |
| 567 *mb = mask_lsb + mask_width - 1; | 818 *mb = mask_lsb + mask_width - 1; |
| 568 *me = mask_lsb; | 819 *me = mask_lsb; |
| 569 return true; | 820 return true; |
| 570 } | 821 } |
| 571 #endif | 822 #endif |
| 572 | 823 |
| 573 void InstructionSelector::VisitWord32And(Node* node) { | 824 void InstructionSelector::VisitWord32And(Node* node) { |
| 574 VisitBinop<Int32BinopMatcher>(this, node, kS390_And32, kUint32Imm); | 825 VisitBin32op(this, node, kS390_And32, |
| 826 BitWiseOperandMode | OperandMode::kAllowRM); |
| 575 } | 827 } |
| 576 | 828 |
| 577 #if V8_TARGET_ARCH_S390X | 829 #if V8_TARGET_ARCH_S390X |
| 578 void InstructionSelector::VisitWord64And(Node* node) { | 830 void InstructionSelector::VisitWord64And(Node* node) { |
| 579 S390OperandGenerator g(this); | 831 S390OperandGenerator g(this); |
| 580 Int64BinopMatcher m(node); | 832 Int64BinopMatcher m(node); |
| 581 int mb = 0; | 833 int mb = 0; |
| 582 int me = 0; | 834 int me = 0; |
| 583 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) { | 835 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) { |
| 584 int sh = 0; | 836 int sh = 0; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 opcode = kS390_RotLeftAndClear64; | 868 opcode = kS390_RotLeftAndClear64; |
| 617 mask = mb; | 869 mask = mb; |
| 618 } | 870 } |
| 619 if (match) { | 871 if (match) { |
| 620 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), | 872 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), |
| 621 g.TempImmediate(sh), g.TempImmediate(mask)); | 873 g.TempImmediate(sh), g.TempImmediate(mask)); |
| 622 return; | 874 return; |
| 623 } | 875 } |
| 624 } | 876 } |
| 625 } | 877 } |
| 626 VisitBinop<Int64BinopMatcher>(this, node, kS390_And64, kUint32Imm); | 878 VisitBinop<Int64BinopMatcher>(this, node, kS390_And64, |
| 879 OperandMode::kUint32Imm); |
| 627 } | 880 } |
| 628 #endif | 881 #endif |
| 629 | 882 |
| 630 void InstructionSelector::VisitWord32Or(Node* node) { | 883 void InstructionSelector::VisitWord32Or(Node* node) { |
| 631 Int32BinopMatcher m(node); | 884 VisitBin32op(this, node, kS390_Or32, |
| 632 VisitBinop<Int32BinopMatcher>(this, node, kS390_Or32, kUint32Imm); | 885 BitWiseOperandMode | OperandMode::kAllowRM); |
| 633 } | 886 } |
| 634 | 887 |
| 635 #if V8_TARGET_ARCH_S390X | 888 #if V8_TARGET_ARCH_S390X |
| 636 void InstructionSelector::VisitWord64Or(Node* node) { | 889 void InstructionSelector::VisitWord64Or(Node* node) { |
| 637 Int64BinopMatcher m(node); | 890 Int64BinopMatcher m(node); |
| 638 VisitBinop<Int64BinopMatcher>(this, node, kS390_Or64, kUint32Imm); | 891 VisitBinop<Int64BinopMatcher>(this, node, kS390_Or64, |
| 892 OperandMode::kUint32Imm); |
| 639 } | 893 } |
| 640 #endif | 894 #endif |
| 641 | 895 |
| 642 void InstructionSelector::VisitWord32Xor(Node* node) { | 896 void InstructionSelector::VisitWord32Xor(Node* node) { |
| 643 S390OperandGenerator g(this); | 897 VisitBin32op(this, node, kS390_Xor32, |
| 644 Int32BinopMatcher m(node); | 898 BitWiseOperandMode | OperandMode::kAllowRM); |
| 645 if (m.right().Is(-1)) { | |
| 646 Emit(kS390_Not32, g.DefineAsRegister(node), g.UseRegister(m.left().node())); | |
| 647 } else { | |
| 648 VisitBinop<Int32BinopMatcher>(this, node, kS390_Xor32, kUint32Imm); | |
| 649 } | |
| 650 } | 899 } |
| 651 | 900 |
| 652 #if V8_TARGET_ARCH_S390X | 901 #if V8_TARGET_ARCH_S390X |
| 653 void InstructionSelector::VisitWord64Xor(Node* node) { | 902 void InstructionSelector::VisitWord64Xor(Node* node) { |
| 654 S390OperandGenerator g(this); | 903 VisitBinop<Int64BinopMatcher>(this, node, kS390_Xor64, |
| 655 Int64BinopMatcher m(node); | 904 OperandMode::kUint32Imm); |
| 656 if (m.right().Is(-1)) { | |
| 657 Emit(kS390_Not64, g.DefineAsRegister(node), g.UseRegister(m.left().node())); | |
| 658 } else { | |
| 659 VisitBinop<Int64BinopMatcher>(this, node, kS390_Xor64, kUint32Imm); | |
| 660 } | |
| 661 } | 905 } |
| 662 #endif | 906 #endif |
| 663 | 907 |
| 664 void InstructionSelector::VisitWord32Shl(Node* node) { | 908 void InstructionSelector::VisitWord32Shl(Node* node) { |
| 665 VisitRRO(this, kS390_ShiftLeft32, node, kShift32Imm); | 909 VisitBin32op(this, node, kS390_ShiftLeft32, BitWiseOperandMode); |
| 666 } | 910 } |
| 667 | 911 |
| 668 #if V8_TARGET_ARCH_S390X | 912 #if V8_TARGET_ARCH_S390X |
| 669 void InstructionSelector::VisitWord64Shl(Node* node) { | 913 void InstructionSelector::VisitWord64Shl(Node* node) { |
| 670 S390OperandGenerator g(this); | 914 S390OperandGenerator g(this); |
| 671 Int64BinopMatcher m(node); | 915 Int64BinopMatcher m(node); |
| 672 // TODO(mbrandy): eliminate left sign extension if right >= 32 | 916 // TODO(mbrandy): eliminate left sign extension if right >= 32 |
| 673 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { | 917 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { |
| 674 Int64BinopMatcher mleft(m.left().node()); | 918 Int64BinopMatcher mleft(m.left().node()); |
| 675 int sh = m.right().Value(); | 919 int sh = m.right().Value(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 698 } | 942 } |
| 699 if (match) { | 943 if (match) { |
| 700 Emit(opcode, g.DefineAsRegister(node), | 944 Emit(opcode, g.DefineAsRegister(node), |
| 701 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), | 945 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), |
| 702 g.TempImmediate(mask)); | 946 g.TempImmediate(mask)); |
| 703 return; | 947 return; |
| 704 } | 948 } |
| 705 } | 949 } |
| 706 } | 950 } |
| 707 } | 951 } |
| 708 VisitRRO(this, kS390_ShiftLeft64, node, kShift64Imm); | 952 VisitRRO(this, kS390_ShiftLeft64, node, OperandMode::kShift64Imm); |
| 709 } | 953 } |
| 710 #endif | 954 #endif |
| 711 | 955 |
| 712 void InstructionSelector::VisitWord32Shr(Node* node) { | 956 void InstructionSelector::VisitWord32Shr(Node* node) { |
| 713 VisitRRO(this, kS390_ShiftRight32, node, kShift32Imm); | 957 VisitBin32op(this, node, kS390_ShiftRight32, BitWiseOperandMode); |
| 714 } | 958 } |
| 715 | 959 |
| 716 #if V8_TARGET_ARCH_S390X | 960 #if V8_TARGET_ARCH_S390X |
| 717 void InstructionSelector::VisitWord64Shr(Node* node) { | 961 void InstructionSelector::VisitWord64Shr(Node* node) { |
| 718 S390OperandGenerator g(this); | 962 S390OperandGenerator g(this); |
| 719 Int64BinopMatcher m(node); | 963 Int64BinopMatcher m(node); |
| 720 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { | 964 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { |
| 721 Int64BinopMatcher mleft(m.left().node()); | 965 Int64BinopMatcher mleft(m.left().node()); |
| 722 int sh = m.right().Value(); | 966 int sh = m.right().Value(); |
| 723 int mb; | 967 int mb; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 742 } | 986 } |
| 743 if (match) { | 987 if (match) { |
| 744 Emit(opcode, g.DefineAsRegister(node), | 988 Emit(opcode, g.DefineAsRegister(node), |
| 745 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), | 989 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), |
| 746 g.TempImmediate(mask)); | 990 g.TempImmediate(mask)); |
| 747 return; | 991 return; |
| 748 } | 992 } |
| 749 } | 993 } |
| 750 } | 994 } |
| 751 } | 995 } |
| 752 VisitRRO(this, kS390_ShiftRight64, node, kShift64Imm); | 996 VisitRRO(this, kS390_ShiftRight64, node, OperandMode::kShift64Imm); |
| 753 } | 997 } |
| 754 #endif | 998 #endif |
| 755 | 999 |
| 756 void InstructionSelector::VisitWord32Sar(Node* node) { | 1000 void InstructionSelector::VisitWord32Sar(Node* node) { |
| 757 S390OperandGenerator g(this); | 1001 S390OperandGenerator g(this); |
| 758 Int32BinopMatcher m(node); | 1002 Int32BinopMatcher m(node); |
| 759 // Replace with sign extension for (x << K) >> K where K is 16 or 24. | 1003 // Replace with sign extension for (x << K) >> K where K is 16 or 24. |
| 760 if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) { | 1004 if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) { |
| 761 Int32BinopMatcher mleft(m.left().node()); | 1005 Int32BinopMatcher mleft(m.left().node()); |
| 762 if (mleft.right().Is(16) && m.right().Is(16)) { | 1006 if (mleft.right().Is(16) && m.right().Is(16)) { |
| 763 Emit(kS390_ExtendSignWord16, g.DefineAsRegister(node), | 1007 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node()); |
| 764 g.UseRegister(mleft.left().node())); | 1008 Emit(kS390_ExtendSignWord16, |
| 1009 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node), |
| 1010 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt)); |
| 765 return; | 1011 return; |
| 766 } else if (mleft.right().Is(24) && m.right().Is(24)) { | 1012 } else if (mleft.right().Is(24) && m.right().Is(24)) { |
| 767 Emit(kS390_ExtendSignWord8, g.DefineAsRegister(node), | 1013 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node()); |
| 768 g.UseRegister(mleft.left().node())); | 1014 Emit(kS390_ExtendSignWord8, |
| 1015 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node), |
| 1016 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt)); |
| 769 return; | 1017 return; |
| 770 } | 1018 } |
| 771 } | 1019 } |
| 772 VisitRRO(this, kS390_ShiftRightArith32, node, kShift32Imm); | 1020 VisitBin32op(this, node, kS390_ShiftRightArith32, BitWiseOperandMode); |
| 773 } | 1021 } |
| 774 | 1022 |
| 775 #if !V8_TARGET_ARCH_S390X | 1023 #if !V8_TARGET_ARCH_S390X |
| 776 void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode, | 1024 void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode, |
| 777 InstructionCode opcode2, Node* node) { | 1025 InstructionCode opcode2, Node* node) { |
| 778 S390OperandGenerator g(selector); | 1026 S390OperandGenerator g(selector); |
| 779 | 1027 |
| 780 Node* projection1 = NodeProperties::FindProjection(node, 1); | 1028 Node* projection1 = NodeProperties::FindProjection(node, 1); |
| 781 if (projection1) { | 1029 if (projection1) { |
| 782 // We use UseUniqueRegister here to avoid register sharing with the output | 1030 // We use UseUniqueRegister here to avoid register sharing with the output |
| 783 // registers. | 1031 // registers. |
| 784 InstructionOperand inputs[] = { | 1032 InstructionOperand inputs[] = { |
| 785 g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)), | 1033 g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)), |
| 786 g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))}; | 1034 g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))}; |
| 787 | 1035 |
| 788 InstructionOperand outputs[] = { | 1036 InstructionOperand outputs[] = { |
| 789 g.DefineAsRegister(node), | 1037 g.DefineAsRegister(node), |
| 790 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; | 1038 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; |
| 791 | 1039 |
| 792 selector->Emit(opcode, 2, outputs, 4, inputs); | 1040 selector->Emit(opcode, 2, outputs, 4, inputs); |
| 793 } else { | 1041 } else { |
| 794 // The high word of the result is not used, so we emit the standard 32 bit | 1042 // The high word of the result is not used, so we emit the standard 32 bit |
| 795 // instruction. | 1043 // instruction. |
| 796 selector->Emit(opcode2, g.DefineSameAsFirst(node), | 1044 selector->Emit(opcode2, g.DefineSameAsFirst(node), |
| 797 g.UseRegister(node->InputAt(0)), | 1045 g.UseRegister(node->InputAt(0)), |
| 798 g.UseRegister(node->InputAt(2))); | 1046 g.UseRegister(node->InputAt(2)), g.TempImmediate(0)); |
| 799 } | 1047 } |
| 800 } | 1048 } |
| 801 | 1049 |
| 802 void InstructionSelector::VisitInt32PairAdd(Node* node) { | 1050 void InstructionSelector::VisitInt32PairAdd(Node* node) { |
| 803 VisitPairBinop(this, kS390_AddPair, kS390_Add32, node); | 1051 VisitPairBinop(this, kS390_AddPair, kS390_Add32, node); |
| 804 } | 1052 } |
| 805 | 1053 |
| 806 void InstructionSelector::VisitInt32PairSub(Node* node) { | 1054 void InstructionSelector::VisitInt32PairSub(Node* node) { |
| 807 VisitPairBinop(this, kS390_SubPair, kS390_Sub32, node); | 1055 VisitPairBinop(this, kS390_SubPair, kS390_Sub32, node); |
| 808 } | 1056 } |
| 809 | 1057 |
| 810 void InstructionSelector::VisitInt32PairMul(Node* node) { | 1058 void InstructionSelector::VisitInt32PairMul(Node* node) { |
| 811 S390OperandGenerator g(this); | 1059 S390OperandGenerator g(this); |
| 812 Node* projection1 = NodeProperties::FindProjection(node, 1); | 1060 Node* projection1 = NodeProperties::FindProjection(node, 1); |
| 813 if (projection1) { | 1061 if (projection1) { |
| 814 InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)), | 1062 InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)), |
| 815 g.UseUniqueRegister(node->InputAt(1)), | 1063 g.UseUniqueRegister(node->InputAt(1)), |
| 816 g.UseUniqueRegister(node->InputAt(2)), | 1064 g.UseUniqueRegister(node->InputAt(2)), |
| 817 g.UseUniqueRegister(node->InputAt(3))}; | 1065 g.UseUniqueRegister(node->InputAt(3))}; |
| 818 | 1066 |
| 819 InstructionOperand outputs[] = { | 1067 InstructionOperand outputs[] = { |
| 820 g.DefineAsRegister(node), | 1068 g.DefineAsRegister(node), |
| 821 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; | 1069 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; |
| 822 | 1070 |
| 823 Emit(kS390_MulPair, 2, outputs, 4, inputs); | 1071 Emit(kS390_MulPair, 2, outputs, 4, inputs); |
| 824 } else { | 1072 } else { |
| 825 // The high word of the result is not used, so we emit the standard 32 bit | 1073 // The high word of the result is not used, so we emit the standard 32 bit |
| 826 // instruction. | 1074 // instruction. |
| 827 Emit(kS390_Mul32, g.DefineSameAsFirst(node), | 1075 Emit(kS390_Mul32, g.DefineSameAsFirst(node), |
| 828 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(2))); | 1076 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(2)), |
| 1077 g.TempImmediate(0)); |
| 829 } | 1078 } |
| 830 } | 1079 } |
| 831 | 1080 |
| 832 namespace { | 1081 namespace { |
| 833 // Shared routine for multiple shift operations. | 1082 // Shared routine for multiple shift operations. |
| 834 void VisitPairShift(InstructionSelector* selector, InstructionCode opcode, | 1083 void VisitPairShift(InstructionSelector* selector, InstructionCode opcode, |
| 835 Node* node) { | 1084 Node* node) { |
| 836 S390OperandGenerator g(selector); | 1085 S390OperandGenerator g(selector); |
| 837 // We use g.UseUniqueRegister here to guarantee that there is | 1086 // We use g.UseUniqueRegister here to guarantee that there is |
| 838 // no register aliasing of input registers with output registers. | 1087 // no register aliasing of input registers with output registers. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 VisitPairShift(this, kS390_ShiftRightPair, node); | 1123 VisitPairShift(this, kS390_ShiftRightPair, node); |
| 875 } | 1124 } |
| 876 | 1125 |
| 877 void InstructionSelector::VisitWord32PairSar(Node* node) { | 1126 void InstructionSelector::VisitWord32PairSar(Node* node) { |
| 878 VisitPairShift(this, kS390_ShiftRightArithPair, node); | 1127 VisitPairShift(this, kS390_ShiftRightArithPair, node); |
| 879 } | 1128 } |
| 880 #endif | 1129 #endif |
| 881 | 1130 |
| 882 #if V8_TARGET_ARCH_S390X | 1131 #if V8_TARGET_ARCH_S390X |
| 883 void InstructionSelector::VisitWord64Sar(Node* node) { | 1132 void InstructionSelector::VisitWord64Sar(Node* node) { |
| 884 VisitRRO(this, kS390_ShiftRightArith64, node, kShift64Imm); | 1133 VisitRRO(this, kS390_ShiftRightArith64, node, OperandMode::kShift64Imm); |
| 885 } | 1134 } |
| 886 #endif | 1135 #endif |
| 887 | 1136 |
| 888 void InstructionSelector::VisitWord32Ror(Node* node) { | 1137 void InstructionSelector::VisitWord32Ror(Node* node) { |
| 889 VisitRRO(this, kS390_RotRight32, node, kShift32Imm); | 1138 // TODO(john): match dst = ror(src1, src2 + imm) |
| 1139 VisitBin32op(this, node, kS390_RotRight32, |
| 1140 OperandMode::kAllowRI | OperandMode::kAllowRRR | |
| 1141 OperandMode::kAllowRRI | OperandMode::kShift32Imm); |
| 890 } | 1142 } |
| 891 | 1143 |
| 892 #if V8_TARGET_ARCH_S390X | 1144 #if V8_TARGET_ARCH_S390X |
| 893 void InstructionSelector::VisitWord64Ror(Node* node) { | 1145 void InstructionSelector::VisitWord64Ror(Node* node) { |
| 894 VisitRRO(this, kS390_RotRight64, node, kShift64Imm); | 1146 VisitRRO(this, kS390_RotRight64, node, OperandMode::kShift64Imm); |
| 895 } | 1147 } |
| 896 #endif | 1148 #endif |
| 897 | 1149 |
| 898 void InstructionSelector::VisitWord32Clz(Node* node) { | 1150 void InstructionSelector::VisitWord32Clz(Node* node) { |
| 899 S390OperandGenerator g(this); | 1151 S390OperandGenerator g(this); |
| 900 Emit(kS390_Cntlz32, g.DefineAsRegister(node), | 1152 Emit(kS390_Cntlz32, g.DefineAsRegister(node), |
| 901 g.UseRegister(node->InputAt(0))); | 1153 g.UseRegister(node->InputAt(0))); |
| 902 } | 1154 } |
| 903 | 1155 |
| 904 #if V8_TARGET_ARCH_S390X | 1156 #if V8_TARGET_ARCH_S390X |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 954 g.DefineAsRegister(node), g.UseRegister(base), | 1206 g.DefineAsRegister(node), g.UseRegister(base), |
| 955 g.UseRegister(offset)); | 1207 g.UseRegister(offset)); |
| 956 return; | 1208 return; |
| 957 } | 1209 } |
| 958 } | 1210 } |
| 959 Emit(kS390_LoadReverse32RR, g.DefineAsRegister(node), | 1211 Emit(kS390_LoadReverse32RR, g.DefineAsRegister(node), |
| 960 g.UseRegister(node->InputAt(0))); | 1212 g.UseRegister(node->InputAt(0))); |
| 961 } | 1213 } |
| 962 | 1214 |
| 963 void InstructionSelector::VisitInt32Add(Node* node) { | 1215 void InstructionSelector::VisitInt32Add(Node* node) { |
| 964 VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm); | 1216 VisitBin32op(this, node, kS390_Add32, AddOperandMode); |
| 965 } | 1217 } |
| 966 | 1218 |
| 967 #if V8_TARGET_ARCH_S390X | 1219 #if V8_TARGET_ARCH_S390X |
| 968 void InstructionSelector::VisitInt64Add(Node* node) { | 1220 void InstructionSelector::VisitInt64Add(Node* node) { |
| 969 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm); | 1221 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, |
| 1222 OperandMode::kInt32Imm); |
| 970 } | 1223 } |
| 971 #endif | 1224 #endif |
| 972 | 1225 |
| 973 void InstructionSelector::VisitInt32Sub(Node* node) { | 1226 void InstructionSelector::VisitInt32Sub(Node* node) { |
| 974 S390OperandGenerator g(this); | 1227 S390OperandGenerator g(this); |
| 975 Int32BinopMatcher m(node); | 1228 Int32BinopMatcher m(node); |
| 976 if (m.left().Is(0)) { | 1229 if (m.left().Is(0)) { |
| 977 Emit(kS390_Neg32, g.DefineAsRegister(node), | 1230 Node* right = m.right().node(); |
| 978 g.UseRegister(m.right().node())); | 1231 bool doZeroExt = ZeroExtendsWord32ToWord64(right); |
| 1232 Emit(kS390_Neg32, g.DefineAsRegister(node), g.UseRegister(right), |
| 1233 g.TempImmediate(doZeroExt)); |
| 979 } else { | 1234 } else { |
| 980 VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt32Imm_Negate); | 1235 VisitBin32op(this, node, kS390_Sub32, SubOperandMode); |
| 981 } | 1236 } |
| 982 } | 1237 } |
| 983 | 1238 |
| 984 #if V8_TARGET_ARCH_S390X | 1239 #if V8_TARGET_ARCH_S390X |
| 985 void InstructionSelector::VisitInt64Sub(Node* node) { | 1240 void InstructionSelector::VisitInt64Sub(Node* node) { |
| 986 S390OperandGenerator g(this); | 1241 S390OperandGenerator g(this); |
| 987 Int64BinopMatcher m(node); | 1242 Int64BinopMatcher m(node); |
| 988 if (m.left().Is(0)) { | 1243 if (m.left().Is(0)) { |
| 989 Emit(kS390_Neg64, g.DefineAsRegister(node), | 1244 Emit(kS390_Neg64, g.DefineAsRegister(node), |
| 990 g.UseRegister(m.right().node())); | 1245 g.UseRegister(m.right().node())); |
| 991 } else { | 1246 } else { |
| 992 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt32Imm_Negate); | 1247 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, |
| 1248 OperandMode::kInt32Imm_Negate); |
| 993 } | 1249 } |
| 994 } | 1250 } |
| 995 #endif | 1251 #endif |
| 996 | 1252 |
| 997 namespace { | 1253 namespace { |
| 998 | 1254 |
| 999 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1255 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 1000 InstructionOperand left, InstructionOperand right, | 1256 InstructionOperand left, InstructionOperand right, |
| 1001 FlagsContinuation* cont); | 1257 FlagsContinuation* cont); |
| 1002 void EmitInt32MulWithOverflow(InstructionSelector* selector, Node* node, | |
| 1003 FlagsContinuation* cont) { | |
| 1004 S390OperandGenerator g(selector); | |
| 1005 Int32BinopMatcher m(node); | |
| 1006 InstructionOperand result_operand = g.DefineAsRegister(node); | |
| 1007 InstructionOperand high32_operand = g.TempRegister(); | |
| 1008 InstructionOperand temp_operand = g.TempRegister(); | |
| 1009 { | |
| 1010 InstructionOperand outputs[] = {result_operand, high32_operand}; | |
| 1011 InstructionOperand inputs[] = {g.UseRegister(m.left().node()), | |
| 1012 g.UseRegister(m.right().node())}; | |
| 1013 selector->Emit(kS390_Mul32WithHigh32, 2, outputs, 2, inputs); | |
| 1014 } | |
| 1015 { | |
| 1016 InstructionOperand shift_31 = g.UseImmediate(31); | |
| 1017 InstructionOperand outputs[] = {temp_operand}; | |
| 1018 InstructionOperand inputs[] = {result_operand, shift_31}; | |
| 1019 selector->Emit(kS390_ShiftRightArith32, 1, outputs, 2, inputs); | |
| 1020 } | |
| 1021 | 1258 |
| 1022 VisitCompare(selector, kS390_Cmp32, high32_operand, temp_operand, cont); | 1259 #if V8_TARGET_ARCH_S390X |
| 1023 } | |
| 1024 | |
| 1025 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | 1260 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| 1026 S390OperandGenerator g(selector); | 1261 S390OperandGenerator g(selector); |
| 1027 Int32BinopMatcher m(node); | 1262 Int32BinopMatcher m(node); |
| 1028 Node* left = m.left().node(); | 1263 Node* left = m.left().node(); |
| 1029 Node* right = m.right().node(); | 1264 Node* right = m.right().node(); |
| 1030 if (g.CanBeImmediate(right, kInt32Imm)) { | 1265 if (g.CanBeImmediate(right, OperandMode::kInt32Imm)) { |
| 1031 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 1266 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 1032 g.UseImmediate(right)); | 1267 g.UseImmediate(right)); |
| 1033 } else { | 1268 } else { |
| 1034 if (g.CanBeBetterLeftOperand(right)) { | 1269 if (g.CanBeBetterLeftOperand(right)) { |
| 1035 std::swap(left, right); | 1270 std::swap(left, right); |
| 1036 } | 1271 } |
| 1037 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 1272 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 1038 g.Use(right)); | 1273 g.Use(right)); |
| 1039 } | 1274 } |
| 1040 } | 1275 } |
| 1276 #endif |
| 1041 | 1277 |
| 1042 } // namespace | 1278 } // namespace |
| 1043 | 1279 |
| 1044 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) { | 1280 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) { |
| 1045 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1281 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1046 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf); | 1282 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf); |
| 1047 return EmitInt32MulWithOverflow(this, node, &cont); | 1283 return VisitBin32op(this, node, kS390_Mul32WithOverflow, |
| 1284 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, |
| 1285 &cont); |
| 1048 } | 1286 } |
| 1049 VisitMul(this, node, kS390_Mul32); | 1287 VisitBin32op(this, node, kS390_Mul32, MulOperandMode); |
| 1050 // FlagsContinuation cont; | |
| 1051 // EmitInt32MulWithOverflow(this, node, &cont); | |
| 1052 } | 1288 } |
| 1053 | 1289 |
| 1054 void InstructionSelector::VisitInt32Mul(Node* node) { | 1290 void InstructionSelector::VisitInt32Mul(Node* node) { |
| 1055 S390OperandGenerator g(this); | 1291 S390OperandGenerator g(this); |
| 1056 Int32BinopMatcher m(node); | 1292 Int32BinopMatcher m(node); |
| 1057 Node* left = m.left().node(); | 1293 Node* left = m.left().node(); |
| 1058 Node* right = m.right().node(); | 1294 Node* right = m.right().node(); |
| 1059 if (g.CanBeImmediate(right, kInt32Imm) && | 1295 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) && |
| 1060 base::bits::IsPowerOfTwo32(g.GetImmediate(right))) { | 1296 base::bits::IsPowerOfTwo32(g.GetImmediate(right))) { |
| 1061 int power = 31 - base::bits::CountLeadingZeros32(g.GetImmediate(right)); | 1297 int power = 31 - base::bits::CountLeadingZeros32(g.GetImmediate(right)); |
| 1062 Emit(kS390_ShiftLeft32, g.DefineSameAsFirst(node), g.UseRegister(left), | 1298 bool doZeroExt = !ZeroExtendsWord32ToWord64(left); |
| 1063 g.UseImmediate(power)); | 1299 InstructionOperand dst = |
| 1300 (doZeroExt && CpuFeatures::IsSupported(DISTINCT_OPS)) |
| 1301 ? g.DefineAsRegister(node) |
| 1302 : g.DefineSameAsFirst(node); |
| 1303 |
| 1304 Emit(kS390_ShiftLeft32, dst, g.UseRegister(left), g.UseImmediate(power), |
| 1305 g.TempImmediate(doZeroExt)); |
| 1064 return; | 1306 return; |
| 1065 } | 1307 } |
| 1066 VisitMul(this, node, kS390_Mul32); | 1308 VisitBin32op(this, node, kS390_Mul32, MulOperandMode); |
| 1067 } | 1309 } |
| 1068 | 1310 |
| 1069 #if V8_TARGET_ARCH_S390X | 1311 #if V8_TARGET_ARCH_S390X |
| 1070 void InstructionSelector::VisitInt64Mul(Node* node) { | 1312 void InstructionSelector::VisitInt64Mul(Node* node) { |
| 1071 S390OperandGenerator g(this); | 1313 S390OperandGenerator g(this); |
| 1072 Int64BinopMatcher m(node); | 1314 Int64BinopMatcher m(node); |
| 1073 Node* left = m.left().node(); | 1315 Node* left = m.left().node(); |
| 1074 Node* right = m.right().node(); | 1316 Node* right = m.right().node(); |
| 1075 if (g.CanBeImmediate(right, kInt32Imm) && | 1317 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) && |
| 1076 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) { | 1318 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) { |
| 1077 int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right)); | 1319 int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right)); |
| 1078 Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left), | 1320 Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 1079 g.UseImmediate(power)); | 1321 g.UseImmediate(power)); |
| 1080 return; | 1322 return; |
| 1081 } | 1323 } |
| 1082 VisitMul(this, node, kS390_Mul64); | 1324 VisitMul(this, node, kS390_Mul64); |
| 1083 } | 1325 } |
| 1084 #endif | 1326 #endif |
| 1085 | 1327 |
| 1086 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 1328 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
| 1087 S390OperandGenerator g(this); | 1329 VisitBin32op(this, node, kS390_MulHigh32, |
| 1088 Int32BinopMatcher m(node); | 1330 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps); |
| 1089 Node* left = m.left().node(); | |
| 1090 Node* right = m.right().node(); | |
| 1091 if (g.CanBeBetterLeftOperand(right)) { | |
| 1092 std::swap(left, right); | |
| 1093 } | |
| 1094 Emit(kS390_MulHigh32, g.DefineAsRegister(node), g.UseRegister(left), | |
| 1095 g.Use(right)); | |
| 1096 } | 1331 } |
| 1097 | 1332 |
| 1098 void InstructionSelector::VisitUint32MulHigh(Node* node) { | 1333 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
| 1099 S390OperandGenerator g(this); | 1334 S390OperandGenerator g(this); |
| 1100 Int32BinopMatcher m(node); | 1335 Int32BinopMatcher m(node); |
| 1101 Node* left = m.left().node(); | 1336 Node* left = m.left().node(); |
| 1102 Node* right = m.right().node(); | 1337 Node* right = m.right().node(); |
| 1103 if (g.CanBeBetterLeftOperand(right)) { | 1338 if (g.CanBeBetterLeftOperand(right)) { |
| 1104 std::swap(left, right); | 1339 std::swap(left, right); |
| 1105 } | 1340 } |
| 1106 Emit(kS390_MulHighU32, g.DefineAsRegister(node), g.UseRegister(left), | 1341 Emit(kS390_MulHighU32, g.DefineAsRegister(node), g.UseRegister(left), |
| 1107 g.Use(right)); | 1342 g.Use(right)); |
| 1108 } | 1343 } |
| 1109 | 1344 |
| 1110 void InstructionSelector::VisitInt32Div(Node* node) { | 1345 void InstructionSelector::VisitInt32Div(Node* node) { |
| 1111 VisitRRR(this, kS390_Div32, node); | 1346 VisitBin32op(this, node, kS390_Div32, |
| 1347 OperandMode::kAllowRRM | OperandMode::kAllowRRR); |
| 1112 } | 1348 } |
| 1113 | 1349 |
| 1114 #if V8_TARGET_ARCH_S390X | 1350 #if V8_TARGET_ARCH_S390X |
| 1115 void InstructionSelector::VisitInt64Div(Node* node) { | 1351 void InstructionSelector::VisitInt64Div(Node* node) { |
| 1116 VisitRRR(this, kS390_Div64, node); | 1352 VisitRRR(this, kS390_Div64, node); |
| 1117 } | 1353 } |
| 1118 #endif | 1354 #endif |
| 1119 | 1355 |
| 1120 void InstructionSelector::VisitUint32Div(Node* node) { | 1356 void InstructionSelector::VisitUint32Div(Node* node) { |
| 1121 VisitRRR(this, kS390_DivU32, node); | 1357 VisitBin32op(this, node, kS390_DivU32, |
| 1358 OperandMode::kAllowRRM | OperandMode::kAllowRRR); |
| 1122 } | 1359 } |
| 1123 | 1360 |
| 1124 #if V8_TARGET_ARCH_S390X | 1361 #if V8_TARGET_ARCH_S390X |
| 1125 void InstructionSelector::VisitUint64Div(Node* node) { | 1362 void InstructionSelector::VisitUint64Div(Node* node) { |
| 1126 VisitRRR(this, kS390_DivU64, node); | 1363 VisitRRR(this, kS390_DivU64, node); |
| 1127 } | 1364 } |
| 1128 #endif | 1365 #endif |
| 1129 | 1366 |
| 1130 void InstructionSelector::VisitInt32Mod(Node* node) { | 1367 void InstructionSelector::VisitInt32Mod(Node* node) { |
| 1131 VisitRRR(this, kS390_Mod32, node); | 1368 VisitRRR(this, kS390_Mod32, node); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1195 void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) { | 1432 void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) { |
| 1196 VisitTryTruncateDouble(this, kS390_DoubleToUint64, node); | 1433 VisitTryTruncateDouble(this, kS390_DoubleToUint64, node); |
| 1197 } | 1434 } |
| 1198 | 1435 |
| 1199 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { | 1436 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { |
| 1200 // TODO(mbrandy): inspect input to see if nop is appropriate. | 1437 // TODO(mbrandy): inspect input to see if nop is appropriate. |
| 1201 VisitRR(this, kS390_ExtendSignWord32, node); | 1438 VisitRR(this, kS390_ExtendSignWord32, node); |
| 1202 } | 1439 } |
| 1203 | 1440 |
| 1204 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { | 1441 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { |
| 1205 // TODO(mbrandy): inspect input to see if nop is appropriate. | 1442 S390OperandGenerator g(this); |
| 1443 Node* value = node->InputAt(0); |
| 1444 if (ZeroExtendsWord32ToWord64(value)) { |
| 1445 // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the |
| 1446 // zero-extension is a no-op. |
| 1447 return EmitIdentity(node); |
| 1448 } |
| 1206 VisitRR(this, kS390_Uint32ToUint64, node); | 1449 VisitRR(this, kS390_Uint32ToUint64, node); |
| 1207 } | 1450 } |
| 1208 #endif | 1451 #endif |
| 1209 | 1452 |
| 1210 void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { | 1453 void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { |
| 1211 VisitRR(this, kS390_DoubleToFloat32, node); | 1454 VisitRR(this, kS390_DoubleToFloat32, node); |
| 1212 } | 1455 } |
| 1213 | 1456 |
| 1214 void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) { | 1457 void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) { |
| 1215 VisitRR(this, kArchTruncateDoubleToI, node); | 1458 VisitRR(this, kArchTruncateDoubleToI, node); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 | 1644 |
| 1402 void InstructionSelector::VisitFloat32Neg(Node* node) { | 1645 void InstructionSelector::VisitFloat32Neg(Node* node) { |
| 1403 VisitRR(this, kS390_NegFloat, node); | 1646 VisitRR(this, kS390_NegFloat, node); |
| 1404 } | 1647 } |
| 1405 | 1648 |
| 1406 void InstructionSelector::VisitFloat64Neg(Node* node) { | 1649 void InstructionSelector::VisitFloat64Neg(Node* node) { |
| 1407 VisitRR(this, kS390_NegDouble, node); | 1650 VisitRR(this, kS390_NegDouble, node); |
| 1408 } | 1651 } |
| 1409 | 1652 |
| 1410 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1653 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
| 1654 OperandModes mode = AddOperandMode; |
| 1411 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1655 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1412 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 1656 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
| 1413 return VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm, | 1657 return VisitBin32op(this, node, kS390_Add32, mode, &cont); |
| 1414 &cont); | |
| 1415 } | 1658 } |
| 1416 FlagsContinuation cont; | 1659 FlagsContinuation cont; |
| 1417 VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm, &cont); | 1660 VisitBin32op(this, node, kS390_Add32, mode, &cont); |
| 1418 } | 1661 } |
| 1419 | 1662 |
| 1420 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 1663 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
| 1664 OperandModes mode = SubOperandMode; |
| 1421 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1665 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1422 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 1666 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
| 1423 return VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, | 1667 return VisitBin32op(this, node, kS390_Sub32, mode, &cont); |
| 1424 kInt32Imm_Negate, &cont); | |
| 1425 } | 1668 } |
| 1426 FlagsContinuation cont; | 1669 FlagsContinuation cont; |
| 1427 VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt32Imm_Negate, | 1670 VisitBin32op(this, node, kS390_Sub32, mode, &cont); |
| 1428 &cont); | |
| 1429 } | 1671 } |
| 1430 | 1672 |
| 1431 #if V8_TARGET_ARCH_S390X | 1673 #if V8_TARGET_ARCH_S390X |
| 1432 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { | 1674 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { |
| 1433 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1675 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1434 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 1676 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
| 1435 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm, | 1677 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, |
| 1436 &cont); | 1678 OperandMode::kInt32Imm, &cont); |
| 1437 } | 1679 } |
| 1438 FlagsContinuation cont; | 1680 FlagsContinuation cont; |
| 1439 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm, &cont); | 1681 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, OperandMode::kInt32Imm, |
| 1682 &cont); |
| 1440 } | 1683 } |
| 1441 | 1684 |
| 1442 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { | 1685 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { |
| 1443 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1686 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1444 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 1687 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
| 1445 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, | 1688 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, |
| 1446 kInt32Imm_Negate, &cont); | 1689 OperandMode::kInt32Imm_Negate, &cont); |
| 1447 } | 1690 } |
| 1448 FlagsContinuation cont; | 1691 FlagsContinuation cont; |
| 1449 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt32Imm_Negate, | 1692 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, |
| 1450 &cont); | 1693 OperandMode::kInt32Imm_Negate, &cont); |
| 1451 } | 1694 } |
| 1452 #endif | 1695 #endif |
| 1453 | 1696 |
| 1454 static bool CompareLogical(FlagsContinuation* cont) { | 1697 static bool CompareLogical(FlagsContinuation* cont) { |
| 1455 switch (cont->condition()) { | 1698 switch (cont->condition()) { |
| 1456 case kUnsignedLessThan: | 1699 case kUnsignedLessThan: |
| 1457 case kUnsignedGreaterThanOrEqual: | 1700 case kUnsignedGreaterThanOrEqual: |
| 1458 case kUnsignedLessThanOrEqual: | 1701 case kUnsignedLessThanOrEqual: |
| 1459 case kUnsignedGreaterThan: | 1702 case kUnsignedGreaterThan: |
| 1460 return true; | 1703 return true; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1481 cont->frame_state()); | 1724 cont->frame_state()); |
| 1482 } else { | 1725 } else { |
| 1483 DCHECK(cont->IsSet()); | 1726 DCHECK(cont->IsSet()); |
| 1484 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1727 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
| 1485 } | 1728 } |
| 1486 } | 1729 } |
| 1487 | 1730 |
| 1488 // Shared routine for multiple word compare operations. | 1731 // Shared routine for multiple word compare operations. |
| 1489 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1732 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 1490 InstructionCode opcode, FlagsContinuation* cont, | 1733 InstructionCode opcode, FlagsContinuation* cont, |
| 1491 bool commutative, ImmediateMode immediate_mode) { | 1734 bool commutative, OperandModes immediate_mode) { |
| 1492 S390OperandGenerator g(selector); | 1735 S390OperandGenerator g(selector); |
| 1493 Node* left = node->InputAt(0); | 1736 Node* left = node->InputAt(0); |
| 1494 Node* right = node->InputAt(1); | 1737 Node* right = node->InputAt(1); |
| 1495 | 1738 |
| 1496 // Match immediates on left or right side of comparison. | 1739 // Match immediates on left or right side of comparison. |
| 1497 if (g.CanBeImmediate(right, immediate_mode)) { | 1740 if (g.CanBeImmediate(right, immediate_mode)) { |
| 1498 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), | 1741 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), |
| 1499 cont); | 1742 cont); |
| 1500 } else if (g.CanBeImmediate(left, immediate_mode)) { | 1743 } else if (g.CanBeImmediate(left, immediate_mode)) { |
| 1501 if (!commutative) cont->Commute(); | 1744 if (!commutative) cont->Commute(); |
| 1502 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), | 1745 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), |
| 1503 cont); | 1746 cont); |
| 1504 } else { | 1747 } else { |
| 1505 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), | 1748 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), |
| 1506 cont); | 1749 cont); |
| 1507 } | 1750 } |
| 1508 } | 1751 } |
| 1509 | 1752 |
| 1510 void VisitWord32Compare(InstructionSelector* selector, Node* node, | 1753 void VisitWord32Compare(InstructionSelector* selector, Node* node, |
| 1511 FlagsContinuation* cont) { | 1754 FlagsContinuation* cont) { |
| 1512 ImmediateMode mode = (CompareLogical(cont) ? kUint32Imm : kInt32Imm); | 1755 OperandModes mode = |
| 1756 (CompareLogical(cont) ? OperandMode::kUint32Imm : OperandMode::kInt32Imm); |
| 1513 VisitWordCompare(selector, node, kS390_Cmp32, cont, false, mode); | 1757 VisitWordCompare(selector, node, kS390_Cmp32, cont, false, mode); |
| 1514 } | 1758 } |
| 1515 | 1759 |
| 1516 #if V8_TARGET_ARCH_S390X | 1760 #if V8_TARGET_ARCH_S390X |
| 1517 void VisitWord64Compare(InstructionSelector* selector, Node* node, | 1761 void VisitWord64Compare(InstructionSelector* selector, Node* node, |
| 1518 FlagsContinuation* cont) { | 1762 FlagsContinuation* cont) { |
| 1519 ImmediateMode mode = (CompareLogical(cont) ? kUint32Imm : kUint32Imm); | 1763 OperandModes mode = |
| 1764 (CompareLogical(cont) ? OperandMode::kUint32Imm : OperandMode::kInt32Imm); |
| 1520 VisitWordCompare(selector, node, kS390_Cmp64, cont, false, mode); | 1765 VisitWordCompare(selector, node, kS390_Cmp64, cont, false, mode); |
| 1521 } | 1766 } |
| 1522 #endif | 1767 #endif |
| 1523 | 1768 |
| 1524 // Shared routine for multiple float32 compare operations. | 1769 // Shared routine for multiple float32 compare operations. |
| 1525 void VisitFloat32Compare(InstructionSelector* selector, Node* node, | 1770 void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
| 1526 FlagsContinuation* cont) { | 1771 FlagsContinuation* cont) { |
| 1527 S390OperandGenerator g(selector); | 1772 S390OperandGenerator g(selector); |
| 1528 Node* left = node->InputAt(0); | 1773 Node* left = node->InputAt(0); |
| 1529 Node* right = node->InputAt(1); | 1774 Node* right = node->InputAt(1); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 if (m.right().Is(0)) { | 1809 if (m.right().Is(0)) { |
| 1565 // Try to combine the branch with a comparison. | 1810 // Try to combine the branch with a comparison. |
| 1566 Node* const user = m.node(); | 1811 Node* const user = m.node(); |
| 1567 Node* const value = m.left().node(); | 1812 Node* const value = m.left().node(); |
| 1568 if (selector->CanCover(user, value)) { | 1813 if (selector->CanCover(user, value)) { |
| 1569 switch (value->opcode()) { | 1814 switch (value->opcode()) { |
| 1570 case IrOpcode::kInt32Sub: | 1815 case IrOpcode::kInt32Sub: |
| 1571 return VisitWord32Compare(selector, value, cont); | 1816 return VisitWord32Compare(selector, value, cont); |
| 1572 case IrOpcode::kWord32And: | 1817 case IrOpcode::kWord32And: |
| 1573 return VisitWordCompare(selector, value, kS390_Tst64, cont, | 1818 return VisitWordCompare(selector, value, kS390_Tst64, cont, |
| 1574 true, kUint32Imm); | 1819 true, OperandMode::kUint32Imm); |
| 1575 default: | 1820 default: |
| 1576 break; | 1821 break; |
| 1577 } | 1822 } |
| 1578 } | 1823 } |
| 1579 } | 1824 } |
| 1580 return VisitWord32Compare(selector, value, cont); | 1825 return VisitWord32Compare(selector, value, cont); |
| 1581 } | 1826 } |
| 1582 case IrOpcode::kInt32LessThan: | 1827 case IrOpcode::kInt32LessThan: |
| 1583 cont->OverwriteAndNegateIfEqual(kSignedLessThan); | 1828 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
| 1584 return VisitWord32Compare(selector, value, cont); | 1829 return VisitWord32Compare(selector, value, cont); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1598 if (m.right().Is(0)) { | 1843 if (m.right().Is(0)) { |
| 1599 // Try to combine the branch with a comparison. | 1844 // Try to combine the branch with a comparison. |
| 1600 Node* const user = m.node(); | 1845 Node* const user = m.node(); |
| 1601 Node* const value = m.left().node(); | 1846 Node* const value = m.left().node(); |
| 1602 if (selector->CanCover(user, value)) { | 1847 if (selector->CanCover(user, value)) { |
| 1603 switch (value->opcode()) { | 1848 switch (value->opcode()) { |
| 1604 case IrOpcode::kInt64Sub: | 1849 case IrOpcode::kInt64Sub: |
| 1605 return VisitWord64Compare(selector, value, cont); | 1850 return VisitWord64Compare(selector, value, cont); |
| 1606 case IrOpcode::kWord64And: | 1851 case IrOpcode::kWord64And: |
| 1607 return VisitWordCompare(selector, value, kS390_Tst64, cont, | 1852 return VisitWordCompare(selector, value, kS390_Tst64, cont, |
| 1608 true, kUint32Imm); | 1853 true, OperandMode::kUint32Imm); |
| 1609 default: | 1854 default: |
| 1610 break; | 1855 break; |
| 1611 } | 1856 } |
| 1612 } | 1857 } |
| 1613 } | 1858 } |
| 1614 return VisitWord64Compare(selector, value, cont); | 1859 return VisitWord64Compare(selector, value, cont); |
| 1615 } | 1860 } |
| 1616 case IrOpcode::kInt64LessThan: | 1861 case IrOpcode::kInt64LessThan: |
| 1617 cont->OverwriteAndNegateIfEqual(kSignedLessThan); | 1862 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
| 1618 return VisitWord64Compare(selector, value, cont); | 1863 return VisitWord64Compare(selector, value, cont); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1652 // unless the 0th projection (the use of the actual value of the | 1897 // unless the 0th projection (the use of the actual value of the |
| 1653 // <Operation> is either nullptr, which means there's no use of the | 1898 // <Operation> is either nullptr, which means there's no use of the |
| 1654 // actual value, or was already defined, which means it is scheduled | 1899 // actual value, or was already defined, which means it is scheduled |
| 1655 // *AFTER* this branch). | 1900 // *AFTER* this branch). |
| 1656 Node* const node = value->InputAt(0); | 1901 Node* const node = value->InputAt(0); |
| 1657 Node* const result = NodeProperties::FindProjection(node, 0); | 1902 Node* const result = NodeProperties::FindProjection(node, 0); |
| 1658 if (result == nullptr || selector->IsDefined(result)) { | 1903 if (result == nullptr || selector->IsDefined(result)) { |
| 1659 switch (node->opcode()) { | 1904 switch (node->opcode()) { |
| 1660 case IrOpcode::kInt32AddWithOverflow: | 1905 case IrOpcode::kInt32AddWithOverflow: |
| 1661 cont->OverwriteAndNegateIfEqual(kOverflow); | 1906 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 1662 return VisitBinop<Int32BinopMatcher>( | 1907 return VisitBin32op(selector, node, kS390_Add32, AddOperandMode, |
| 1663 selector, node, kS390_Add32, kInt32Imm, cont); | 1908 cont); |
| 1664 case IrOpcode::kInt32SubWithOverflow: | 1909 case IrOpcode::kInt32SubWithOverflow: |
| 1665 cont->OverwriteAndNegateIfEqual(kOverflow); | 1910 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 1666 return VisitBinop<Int32BinopMatcher>( | 1911 return VisitBin32op(selector, node, kS390_Sub32, SubOperandMode, |
| 1667 selector, node, kS390_Sub32, kInt32Imm_Negate, cont); | 1912 cont); |
| 1668 case IrOpcode::kInt32MulWithOverflow: | 1913 case IrOpcode::kInt32MulWithOverflow: |
| 1669 cont->OverwriteAndNegateIfEqual(kNotEqual); | 1914 cont->OverwriteAndNegateIfEqual(kNotEqual); |
| 1670 return EmitInt32MulWithOverflow(selector, node, cont); | 1915 return VisitBin32op( |
| 1916 selector, node, kS390_Mul32WithOverflow, |
| 1917 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, |
| 1918 cont); |
| 1671 #if V8_TARGET_ARCH_S390X | 1919 #if V8_TARGET_ARCH_S390X |
| 1672 case IrOpcode::kInt64AddWithOverflow: | 1920 case IrOpcode::kInt64AddWithOverflow: |
| 1673 cont->OverwriteAndNegateIfEqual(kOverflow); | 1921 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 1674 return VisitBinop<Int64BinopMatcher>( | 1922 return VisitBinop<Int64BinopMatcher>( |
| 1675 selector, node, kS390_Add64, kInt32Imm, cont); | 1923 selector, node, kS390_Add64, OperandMode::kInt32Imm, cont); |
| 1676 case IrOpcode::kInt64SubWithOverflow: | 1924 case IrOpcode::kInt64SubWithOverflow: |
| 1677 cont->OverwriteAndNegateIfEqual(kOverflow); | 1925 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 1678 return VisitBinop<Int64BinopMatcher>( | 1926 return VisitBinop<Int64BinopMatcher>( |
| 1679 selector, node, kS390_Sub64, kInt32Imm_Negate, cont); | 1927 selector, node, kS390_Sub64, OperandMode::kInt32Imm_Negate, |
| 1928 cont); |
| 1680 #endif | 1929 #endif |
| 1681 default: | 1930 default: |
| 1682 break; | 1931 break; |
| 1683 } | 1932 } |
| 1684 } | 1933 } |
| 1685 } | 1934 } |
| 1686 break; | 1935 break; |
| 1687 case IrOpcode::kInt32Sub: | 1936 case IrOpcode::kInt32Sub: |
| 1688 return VisitWord32Compare(selector, value, cont); | 1937 return VisitWord32Compare(selector, value, cont); |
| 1689 case IrOpcode::kWord32And: | 1938 case IrOpcode::kWord32And: |
| 1690 return VisitWordCompare(selector, value, kS390_Tst32, cont, true, | 1939 return VisitWordCompare(selector, value, kS390_Tst32, cont, true, |
| 1691 kUint32Imm); | 1940 OperandMode::kUint32Imm); |
| 1692 // TODO(mbrandy): Handle? | 1941 // TODO(mbrandy): Handle? |
| 1693 // case IrOpcode::kInt32Add: | 1942 // case IrOpcode::kInt32Add: |
| 1694 // case IrOpcode::kWord32Or: | 1943 // case IrOpcode::kWord32Or: |
| 1695 // case IrOpcode::kWord32Xor: | 1944 // case IrOpcode::kWord32Xor: |
| 1696 // case IrOpcode::kWord32Sar: | 1945 // case IrOpcode::kWord32Sar: |
| 1697 // case IrOpcode::kWord32Shl: | 1946 // case IrOpcode::kWord32Shl: |
| 1698 // case IrOpcode::kWord32Shr: | 1947 // case IrOpcode::kWord32Shr: |
| 1699 // case IrOpcode::kWord32Ror: | 1948 // case IrOpcode::kWord32Ror: |
| 1700 #if V8_TARGET_ARCH_S390X | 1949 #if V8_TARGET_ARCH_S390X |
| 1701 case IrOpcode::kInt64Sub: | 1950 case IrOpcode::kInt64Sub: |
| 1702 return VisitWord64Compare(selector, value, cont); | 1951 return VisitWord64Compare(selector, value, cont); |
| 1703 case IrOpcode::kWord64And: | 1952 case IrOpcode::kWord64And: |
| 1704 return VisitWordCompare(selector, value, kS390_Tst64, cont, true, | 1953 return VisitWordCompare(selector, value, kS390_Tst64, cont, true, |
| 1705 kUint32Imm); | 1954 OperandMode::kUint32Imm); |
| 1706 // TODO(mbrandy): Handle? | 1955 // TODO(mbrandy): Handle? |
| 1707 // case IrOpcode::kInt64Add: | 1956 // case IrOpcode::kInt64Add: |
| 1708 // case IrOpcode::kWord64Or: | 1957 // case IrOpcode::kWord64Or: |
| 1709 // case IrOpcode::kWord64Xor: | 1958 // case IrOpcode::kWord64Xor: |
| 1710 // case IrOpcode::kWord64Sar: | 1959 // case IrOpcode::kWord64Sar: |
| 1711 // case IrOpcode::kWord64Shl: | 1960 // case IrOpcode::kWord64Shl: |
| 1712 // case IrOpcode::kWord64Shr: | 1961 // case IrOpcode::kWord64Shr: |
| 1713 // case IrOpcode::kWord64Ror: | 1962 // case IrOpcode::kWord64Ror: |
| 1714 #endif | 1963 #endif |
| 1715 default: | 1964 default: |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1773 size_t table_time_cost = 3; | 2022 size_t table_time_cost = 3; |
| 1774 size_t lookup_space_cost = 3 + 2 * sw.case_count; | 2023 size_t lookup_space_cost = 3 + 2 * sw.case_count; |
| 1775 size_t lookup_time_cost = sw.case_count; | 2024 size_t lookup_time_cost = sw.case_count; |
| 1776 if (sw.case_count > 0 && | 2025 if (sw.case_count > 0 && |
| 1777 table_space_cost + 3 * table_time_cost <= | 2026 table_space_cost + 3 * table_time_cost <= |
| 1778 lookup_space_cost + 3 * lookup_time_cost && | 2027 lookup_space_cost + 3 * lookup_time_cost && |
| 1779 sw.min_value > std::numeric_limits<int32_t>::min()) { | 2028 sw.min_value > std::numeric_limits<int32_t>::min()) { |
| 1780 InstructionOperand index_operand = value_operand; | 2029 InstructionOperand index_operand = value_operand; |
| 1781 if (sw.min_value) { | 2030 if (sw.min_value) { |
| 1782 index_operand = g.TempRegister(); | 2031 index_operand = g.TempRegister(); |
| 1783 Emit(kS390_Sub32, index_operand, value_operand, | 2032 Emit(kS390_Lay | AddressingModeField::encode(kMode_MRI), index_operand, |
| 1784 g.TempImmediate(sw.min_value)); | 2033 value_operand, g.TempImmediate(-sw.min_value)); |
| 1785 } | 2034 } |
| 2035 #if V8_TARGET_ARCH_S390X |
| 2036 InstructionOperand index_operand_zero_ext = g.TempRegister(); |
| 2037 Emit(kS390_Uint32ToUint64, index_operand_zero_ext, index_operand); |
| 2038 index_operand = index_operand_zero_ext; |
| 2039 #endif |
| 1786 // Generate a table lookup. | 2040 // Generate a table lookup. |
| 1787 return EmitTableSwitch(sw, index_operand); | 2041 return EmitTableSwitch(sw, index_operand); |
| 1788 } | 2042 } |
| 1789 | 2043 |
| 1790 // Generate a sequence of conditional jumps. | 2044 // Generate a sequence of conditional jumps. |
| 1791 return EmitLookupSwitch(sw, value_operand); | 2045 return EmitLookupSwitch(sw, value_operand); |
| 1792 } | 2046 } |
| 1793 | 2047 |
| 1794 void InstructionSelector::VisitWord32Equal(Node* const node) { | 2048 void InstructionSelector::VisitWord32Equal(Node* const node) { |
| 1795 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); | 2049 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2046 // static | 2300 // static |
| 2047 MachineOperatorBuilder::AlignmentRequirements | 2301 MachineOperatorBuilder::AlignmentRequirements |
| 2048 InstructionSelector::AlignmentRequirements() { | 2302 InstructionSelector::AlignmentRequirements() { |
| 2049 return MachineOperatorBuilder::AlignmentRequirements:: | 2303 return MachineOperatorBuilder::AlignmentRequirements:: |
| 2050 FullUnalignedAccessSupport(); | 2304 FullUnalignedAccessSupport(); |
| 2051 } | 2305 } |
| 2052 | 2306 |
| 2053 } // namespace compiler | 2307 } // namespace compiler |
| 2054 } // namespace internal | 2308 } // namespace internal |
| 2055 } // namespace v8 | 2309 } // namespace v8 |
| OLD | NEW |