| 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/compiler/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
| 6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
| 7 #include "src/compiler/node-properties-inl.h" | 7 #include "src/compiler/node-properties-inl.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 // Constants in new space cannot be used as immediates in V8 because | 31 // Constants in new space cannot be used as immediates in V8 because |
| 32 // the GC does not scan code objects when collecting the new generation. | 32 // the GC does not scan code objects when collecting the new generation. |
| 33 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); | 33 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); |
| 34 return !isolate()->heap()->InNewSpace(*value.handle()); | 34 return !isolate()->heap()->InNewSpace(*value.handle()); |
| 35 } | 35 } |
| 36 default: | 36 default: |
| 37 return false; | 37 return false; |
| 38 } | 38 } |
| 39 } | 39 } |
| 40 | 40 |
| 41 AddressingMode GenerateMemoryOperandInputs(Node* index, int scale, Node* base, |
| 42 Node* displacement_node, |
| 43 InstructionOperand* inputs[], |
| 44 size_t* input_count) { |
| 45 AddressingMode mode = kMode_MRI; |
| 46 int32_t displacement = (displacement_node == NULL) |
| 47 ? 0 |
| 48 : OpParameter<int32_t>(displacement_node); |
| 49 if (base != NULL) { |
| 50 if (base->opcode() == IrOpcode::kInt32Constant) { |
| 51 displacement += OpParameter<int32_t>(base); |
| 52 base = NULL; |
| 53 } |
| 54 } |
| 55 if (base != NULL) { |
| 56 inputs[(*input_count)++] = UseRegister(base); |
| 57 if (index != NULL) { |
| 58 DCHECK(scale >= 0 && scale <= 3); |
| 59 inputs[(*input_count)++] = UseRegister(index); |
| 60 if (displacement != 0) { |
| 61 inputs[(*input_count)++] = TempImmediate(displacement); |
| 62 static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I, |
| 63 kMode_MR4I, kMode_MR8I}; |
| 64 mode = kMRnI_modes[scale]; |
| 65 } else { |
| 66 static const AddressingMode kMRn_modes[] = {kMode_MR1, kMode_MR2, |
| 67 kMode_MR4, kMode_MR8}; |
| 68 mode = kMRn_modes[scale]; |
| 69 } |
| 70 } else { |
| 71 if (displacement == 0) { |
| 72 mode = kMode_MR; |
| 73 } else { |
| 74 inputs[(*input_count)++] = TempImmediate(displacement); |
| 75 mode = kMode_MRI; |
| 76 } |
| 77 } |
| 78 } else { |
| 79 DCHECK(scale >= 0 && scale <= 3); |
| 80 if (index != NULL) { |
| 81 inputs[(*input_count)++] = UseRegister(index); |
| 82 if (displacement != 0) { |
| 83 inputs[(*input_count)++] = TempImmediate(displacement); |
| 84 static const AddressingMode kMnI_modes[] = {kMode_MRI, kMode_M2I, |
| 85 kMode_M4I, kMode_M8I}; |
| 86 mode = kMnI_modes[scale]; |
| 87 } else { |
| 88 static const AddressingMode kMn_modes[] = {kMode_MR, kMode_M2, |
| 89 kMode_M4, kMode_M8}; |
| 90 mode = kMn_modes[scale]; |
| 91 } |
| 92 } else { |
| 93 inputs[(*input_count)++] = TempImmediate(displacement); |
| 94 return kMode_MI; |
| 95 } |
| 96 } |
| 97 return mode; |
| 98 } |
| 99 |
| 100 AddressingMode GetEffectiveAddressMemoryOperand(Node* node, |
| 101 InstructionOperand* inputs[], |
| 102 size_t* input_count) { |
| 103 BaseWithIndexAndDisplacement32Matcher m(node, true); |
| 104 DCHECK(m.matches()); |
| 105 if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) { |
| 106 return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(), |
| 107 m.displacement(), inputs, input_count); |
| 108 } else { |
| 109 inputs[(*input_count)++] = UseRegister(node->InputAt(0)); |
| 110 inputs[(*input_count)++] = UseRegister(node->InputAt(1)); |
| 111 return kMode_MR1; |
| 112 } |
| 113 } |
| 114 |
| 41 bool CanBeBetterLeftOperand(Node* node) const { | 115 bool CanBeBetterLeftOperand(Node* node) const { |
| 42 return !selector()->IsLive(node); | 116 return !selector()->IsLive(node); |
| 43 } | 117 } |
| 44 }; | 118 }; |
| 45 | 119 |
| 46 | 120 |
| 47 // Get the AddressingMode of scale factor N from the AddressingMode of scale | |
| 48 // factor 1. | |
| 49 static AddressingMode AdjustAddressingMode(AddressingMode base_mode, | |
| 50 int power) { | |
| 51 DCHECK(0 <= power && power < 4); | |
| 52 return static_cast<AddressingMode>(static_cast<int>(base_mode) + power); | |
| 53 } | |
| 54 | |
| 55 | |
| 56 // Fairly intel-specify node matcher used for matching scale factors in | |
| 57 // addressing modes. | |
| 58 // Matches nodes of form [x * N] for N in {1,2,4,8} | |
| 59 class ScaleFactorMatcher : public NodeMatcher { | |
| 60 public: | |
| 61 static const int kMatchedFactors[4]; | |
| 62 | |
| 63 explicit ScaleFactorMatcher(Node* node); | |
| 64 | |
| 65 bool Matches() const { return left_ != NULL; } | |
| 66 int Power() const { | |
| 67 DCHECK(Matches()); | |
| 68 return power_; | |
| 69 } | |
| 70 Node* Left() const { | |
| 71 DCHECK(Matches()); | |
| 72 return left_; | |
| 73 } | |
| 74 | |
| 75 private: | |
| 76 Node* left_; | |
| 77 int power_; | |
| 78 }; | |
| 79 | |
| 80 | |
| 81 // Fairly intel-specify node matcher used for matching index and displacement | |
| 82 // operands in addressing modes. | |
| 83 // Matches nodes of form: | |
| 84 // [x * N] | |
| 85 // [x * N + K] | |
| 86 // [x + K] | |
| 87 // [x] -- fallback case | |
| 88 // for N in {1,2,4,8} and K int32_t | |
| 89 class IndexAndDisplacementMatcher : public NodeMatcher { | |
| 90 public: | |
| 91 explicit IndexAndDisplacementMatcher(Node* node); | |
| 92 | |
| 93 Node* index_node() const { return index_node_; } | |
| 94 int displacement() const { return displacement_; } | |
| 95 int power() const { return power_; } | |
| 96 | |
| 97 private: | |
| 98 Node* index_node_; | |
| 99 int displacement_; | |
| 100 int power_; | |
| 101 }; | |
| 102 | |
| 103 | |
| 104 // Fairly intel-specify node matcher used for matching multiplies that can be | |
| 105 // transformed to lea instructions. | |
| 106 // Matches nodes of form: | |
| 107 // [x * N] | |
| 108 // for N in {1,2,3,4,5,8,9} | |
| 109 class LeaMultiplyMatcher : public NodeMatcher { | |
| 110 public: | |
| 111 static const int kMatchedFactors[7]; | |
| 112 | |
| 113 explicit LeaMultiplyMatcher(Node* node); | |
| 114 | |
| 115 bool Matches() const { return left_ != NULL; } | |
| 116 int Power() const { | |
| 117 DCHECK(Matches()); | |
| 118 return power_; | |
| 119 } | |
| 120 Node* Left() const { | |
| 121 DCHECK(Matches()); | |
| 122 return left_; | |
| 123 } | |
| 124 // Displacement will be either 0 or 1. | |
| 125 int32_t Displacement() const { | |
| 126 DCHECK(Matches()); | |
| 127 return displacement_; | |
| 128 } | |
| 129 | |
| 130 private: | |
| 131 Node* left_; | |
| 132 int power_; | |
| 133 int displacement_; | |
| 134 }; | |
| 135 | |
| 136 | |
| 137 const int ScaleFactorMatcher::kMatchedFactors[] = {1, 2, 4, 8}; | |
| 138 | |
| 139 | |
| 140 ScaleFactorMatcher::ScaleFactorMatcher(Node* node) | |
| 141 : NodeMatcher(node), left_(NULL), power_(0) { | |
| 142 if (opcode() != IrOpcode::kInt32Mul) return; | |
| 143 // TODO(dcarney): should test 64 bit ints as well. | |
| 144 Int32BinopMatcher m(this->node()); | |
| 145 if (!m.right().HasValue()) return; | |
| 146 int32_t value = m.right().Value(); | |
| 147 switch (value) { | |
| 148 case 8: | |
| 149 power_++; // Fall through. | |
| 150 case 4: | |
| 151 power_++; // Fall through. | |
| 152 case 2: | |
| 153 power_++; // Fall through. | |
| 154 case 1: | |
| 155 break; | |
| 156 default: | |
| 157 return; | |
| 158 } | |
| 159 left_ = m.left().node(); | |
| 160 } | |
| 161 | |
| 162 | |
| 163 IndexAndDisplacementMatcher::IndexAndDisplacementMatcher(Node* node) | |
| 164 : NodeMatcher(node), index_node_(node), displacement_(0), power_(0) { | |
| 165 if (opcode() == IrOpcode::kInt32Add) { | |
| 166 Int32BinopMatcher m(this->node()); | |
| 167 if (m.right().HasValue()) { | |
| 168 displacement_ = m.right().Value(); | |
| 169 index_node_ = m.left().node(); | |
| 170 } | |
| 171 } | |
| 172 // Test scale factor. | |
| 173 ScaleFactorMatcher scale_matcher(index_node_); | |
| 174 if (scale_matcher.Matches()) { | |
| 175 index_node_ = scale_matcher.Left(); | |
| 176 power_ = scale_matcher.Power(); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 | |
| 181 const int LeaMultiplyMatcher::kMatchedFactors[7] = {1, 2, 3, 4, 5, 8, 9}; | |
| 182 | |
| 183 | |
| 184 LeaMultiplyMatcher::LeaMultiplyMatcher(Node* node) | |
| 185 : NodeMatcher(node), left_(NULL), power_(0), displacement_(0) { | |
| 186 if (opcode() != IrOpcode::kInt32Mul && opcode() != IrOpcode::kInt64Mul) { | |
| 187 return; | |
| 188 } | |
| 189 int64_t value; | |
| 190 Node* left = NULL; | |
| 191 { | |
| 192 Int32BinopMatcher m(this->node()); | |
| 193 if (m.right().HasValue()) { | |
| 194 value = m.right().Value(); | |
| 195 left = m.left().node(); | |
| 196 } else { | |
| 197 Int64BinopMatcher m(this->node()); | |
| 198 if (m.right().HasValue()) { | |
| 199 value = m.right().Value(); | |
| 200 left = m.left().node(); | |
| 201 } else { | |
| 202 return; | |
| 203 } | |
| 204 } | |
| 205 } | |
| 206 switch (value) { | |
| 207 case 9: | |
| 208 case 8: | |
| 209 power_++; // Fall through. | |
| 210 case 5: | |
| 211 case 4: | |
| 212 power_++; // Fall through. | |
| 213 case 3: | |
| 214 case 2: | |
| 215 power_++; // Fall through. | |
| 216 case 1: | |
| 217 break; | |
| 218 default: | |
| 219 return; | |
| 220 } | |
| 221 if (!base::bits::IsPowerOfTwo64(value)) { | |
| 222 displacement_ = 1; | |
| 223 } | |
| 224 left_ = left; | |
| 225 } | |
| 226 | |
| 227 | |
| 228 class AddressingModeMatcher { | |
| 229 public: | |
| 230 AddressingModeMatcher(IA32OperandGenerator* g, Node* base, Node* index) | |
| 231 : base_operand_(NULL), | |
| 232 index_operand_(NULL), | |
| 233 displacement_operand_(NULL), | |
| 234 mode_(kMode_None) { | |
| 235 Int32Matcher index_imm(index); | |
| 236 if (index_imm.HasValue()) { | |
| 237 int32_t displacement = index_imm.Value(); | |
| 238 // Compute base operand and fold base immediate into displacement. | |
| 239 Int32Matcher base_imm(base); | |
| 240 if (!base_imm.HasValue()) { | |
| 241 base_operand_ = g->UseRegister(base); | |
| 242 } else { | |
| 243 displacement += base_imm.Value(); | |
| 244 } | |
| 245 if (displacement != 0 || base_operand_ == NULL) { | |
| 246 displacement_operand_ = g->TempImmediate(displacement); | |
| 247 } | |
| 248 if (base_operand_ == NULL) { | |
| 249 mode_ = kMode_MI; | |
| 250 } else { | |
| 251 if (displacement == 0) { | |
| 252 mode_ = kMode_MR; | |
| 253 } else { | |
| 254 mode_ = kMode_MRI; | |
| 255 } | |
| 256 } | |
| 257 } else { | |
| 258 // Compute index and displacement. | |
| 259 IndexAndDisplacementMatcher matcher(index); | |
| 260 index_operand_ = g->UseRegister(matcher.index_node()); | |
| 261 int32_t displacement = matcher.displacement(); | |
| 262 // Compute base operand and fold base immediate into displacement. | |
| 263 Int32Matcher base_imm(base); | |
| 264 if (!base_imm.HasValue()) { | |
| 265 base_operand_ = g->UseRegister(base); | |
| 266 } else { | |
| 267 displacement += base_imm.Value(); | |
| 268 } | |
| 269 // Compute displacement operand. | |
| 270 if (displacement != 0) { | |
| 271 displacement_operand_ = g->TempImmediate(displacement); | |
| 272 } | |
| 273 // Compute mode with scale factor one. | |
| 274 if (base_operand_ == NULL) { | |
| 275 if (displacement_operand_ == NULL) { | |
| 276 mode_ = kMode_M1; | |
| 277 } else { | |
| 278 mode_ = kMode_M1I; | |
| 279 } | |
| 280 } else { | |
| 281 if (displacement_operand_ == NULL) { | |
| 282 mode_ = kMode_MR1; | |
| 283 } else { | |
| 284 mode_ = kMode_MR1I; | |
| 285 } | |
| 286 } | |
| 287 // Adjust mode to actual scale factor. | |
| 288 mode_ = AdjustAddressingMode(mode_, matcher.power()); | |
| 289 } | |
| 290 DCHECK_NE(kMode_None, mode_); | |
| 291 } | |
| 292 | |
| 293 size_t SetInputs(InstructionOperand** inputs) { | |
| 294 size_t input_count = 0; | |
| 295 // Compute inputs_ and input_count. | |
| 296 if (base_operand_ != NULL) { | |
| 297 inputs[input_count++] = base_operand_; | |
| 298 } | |
| 299 if (index_operand_ != NULL) { | |
| 300 inputs[input_count++] = index_operand_; | |
| 301 } | |
| 302 if (displacement_operand_ != NULL) { | |
| 303 inputs[input_count++] = displacement_operand_; | |
| 304 } | |
| 305 DCHECK_NE(input_count, 0); | |
| 306 return input_count; | |
| 307 } | |
| 308 | |
| 309 static const int kMaxInputCount = 3; | |
| 310 InstructionOperand* base_operand_; | |
| 311 InstructionOperand* index_operand_; | |
| 312 InstructionOperand* displacement_operand_; | |
| 313 AddressingMode mode_; | |
| 314 }; | |
| 315 | |
| 316 | |
| 317 static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 121 static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, |
| 318 Node* node) { | 122 Node* node) { |
| 319 IA32OperandGenerator g(selector); | 123 IA32OperandGenerator g(selector); |
| 320 selector->Emit(opcode, g.DefineAsRegister(node), | 124 selector->Emit(opcode, g.DefineAsRegister(node), |
| 321 g.UseRegister(node->InputAt(0))); | 125 g.UseRegister(node->InputAt(0))); |
| 322 } | 126 } |
| 323 | 127 |
| 324 | 128 |
| 325 void InstructionSelector::VisitLoad(Node* node) { | 129 void InstructionSelector::VisitLoad(Node* node) { |
| 326 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 130 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
| 327 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 131 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
| 328 Node* base = node->InputAt(0); | |
| 329 Node* index = node->InputAt(1); | |
| 330 | 132 |
| 331 ArchOpcode opcode; | 133 ArchOpcode opcode; |
| 332 // TODO(titzer): signed/unsigned small loads | 134 // TODO(titzer): signed/unsigned small loads |
| 333 switch (rep) { | 135 switch (rep) { |
| 334 case kRepFloat32: | 136 case kRepFloat32: |
| 335 opcode = kIA32Movss; | 137 opcode = kIA32Movss; |
| 336 break; | 138 break; |
| 337 case kRepFloat64: | 139 case kRepFloat64: |
| 338 opcode = kIA32Movsd; | 140 opcode = kIA32Movsd; |
| 339 break; | 141 break; |
| 340 case kRepBit: // Fall through. | 142 case kRepBit: // Fall through. |
| 341 case kRepWord8: | 143 case kRepWord8: |
| 342 opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; | 144 opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; |
| 343 break; | 145 break; |
| 344 case kRepWord16: | 146 case kRepWord16: |
| 345 opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; | 147 opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; |
| 346 break; | 148 break; |
| 347 case kRepTagged: // Fall through. | 149 case kRepTagged: // Fall through. |
| 348 case kRepWord32: | 150 case kRepWord32: |
| 349 opcode = kIA32Movl; | 151 opcode = kIA32Movl; |
| 350 break; | 152 break; |
| 351 default: | 153 default: |
| 352 UNREACHABLE(); | 154 UNREACHABLE(); |
| 353 return; | 155 return; |
| 354 } | 156 } |
| 355 | 157 |
| 356 IA32OperandGenerator g(this); | 158 IA32OperandGenerator g(this); |
| 357 AddressingModeMatcher matcher(&g, base, index); | 159 InstructionOperand* outputs[1]; |
| 358 InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_); | 160 outputs[0] = g.DefineAsRegister(node); |
| 359 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; | 161 InstructionOperand* inputs[3]; |
| 360 InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount]; | 162 size_t input_count = 0; |
| 361 size_t input_count = matcher.SetInputs(inputs); | 163 AddressingMode mode = |
| 164 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
| 165 InstructionCode code = opcode | AddressingModeField::encode(mode); |
| 362 Emit(code, 1, outputs, input_count, inputs); | 166 Emit(code, 1, outputs, input_count, inputs); |
| 363 } | 167 } |
| 364 | 168 |
| 365 | 169 |
| 366 void InstructionSelector::VisitStore(Node* node) { | 170 void InstructionSelector::VisitStore(Node* node) { |
| 367 IA32OperandGenerator g(this); | 171 IA32OperandGenerator g(this); |
| 368 Node* base = node->InputAt(0); | 172 Node* base = node->InputAt(0); |
| 369 Node* index = node->InputAt(1); | 173 Node* index = node->InputAt(1); |
| 370 Node* value = node->InputAt(2); | 174 Node* value = node->InputAt(2); |
| 371 | 175 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 | 214 |
| 411 InstructionOperand* val; | 215 InstructionOperand* val; |
| 412 if (g.CanBeImmediate(value)) { | 216 if (g.CanBeImmediate(value)) { |
| 413 val = g.UseImmediate(value); | 217 val = g.UseImmediate(value); |
| 414 } else if (rep == kRepWord8 || rep == kRepBit) { | 218 } else if (rep == kRepWord8 || rep == kRepBit) { |
| 415 val = g.UseByteRegister(value); | 219 val = g.UseByteRegister(value); |
| 416 } else { | 220 } else { |
| 417 val = g.UseRegister(value); | 221 val = g.UseRegister(value); |
| 418 } | 222 } |
| 419 | 223 |
| 420 AddressingModeMatcher matcher(&g, base, index); | 224 InstructionOperand* inputs[4]; |
| 421 InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_); | 225 size_t input_count = 0; |
| 422 InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount + 1]; | 226 AddressingMode mode = |
| 423 size_t input_count = matcher.SetInputs(inputs); | 227 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
| 228 InstructionCode code = opcode | AddressingModeField::encode(mode); |
| 424 inputs[input_count++] = val; | 229 inputs[input_count++] = val; |
| 425 Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs); | 230 Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs); |
| 426 } | 231 } |
| 427 | 232 |
| 428 | 233 |
| 429 void InstructionSelector::VisitCheckedLoad(Node* node) { | 234 void InstructionSelector::VisitCheckedLoad(Node* node) { |
| 430 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 235 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
| 431 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 236 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
| 432 IA32OperandGenerator g(this); | 237 IA32OperandGenerator g(this); |
| 433 Node* const buffer = node->InputAt(0); | 238 Node* const buffer = node->InputAt(0); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 if (g.CanBeImmediate(right)) { | 464 if (g.CanBeImmediate(right)) { |
| 660 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 465 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 661 g.UseImmediate(right)); | 466 g.UseImmediate(right)); |
| 662 } else { | 467 } else { |
| 663 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 468 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 664 g.UseFixed(right, ecx)); | 469 g.UseFixed(right, ecx)); |
| 665 } | 470 } |
| 666 } | 471 } |
| 667 | 472 |
| 668 | 473 |
| 474 namespace { |
| 475 |
| 476 void VisitMulHigh(InstructionSelector* selector, Node* node, |
| 477 ArchOpcode opcode) { |
| 478 IA32OperandGenerator g(selector); |
| 479 selector->Emit(opcode, g.DefineAsFixed(node, edx), |
| 480 g.UseFixed(node->InputAt(0), eax), |
| 481 g.UseUniqueRegister(node->InputAt(1))); |
| 482 } |
| 483 |
| 484 |
| 485 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| 486 IA32OperandGenerator g(selector); |
| 487 InstructionOperand* temps[] = {g.TempRegister(edx)}; |
| 488 selector->Emit(opcode, g.DefineAsFixed(node, eax), |
| 489 g.UseFixed(node->InputAt(0), eax), |
| 490 g.UseUnique(node->InputAt(1)), arraysize(temps), temps); |
| 491 } |
| 492 |
| 493 |
| 494 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| 495 IA32OperandGenerator g(selector); |
| 496 selector->Emit(opcode, g.DefineAsFixed(node, edx), |
| 497 g.UseFixed(node->InputAt(0), eax), |
| 498 g.UseUnique(node->InputAt(1))); |
| 499 } |
| 500 |
| 501 void EmitLea(InstructionSelector* selector, Node* result, Node* index, |
| 502 int scale, Node* base, Node* displacement) { |
| 503 IA32OperandGenerator g(selector); |
| 504 InstructionOperand* inputs[4]; |
| 505 size_t input_count = 0; |
| 506 AddressingMode mode = g.GenerateMemoryOperandInputs( |
| 507 index, scale, base, displacement, inputs, &input_count); |
| 508 |
| 509 DCHECK_NE(0, static_cast<int>(input_count)); |
| 510 DCHECK_GE(arraysize(inputs), input_count); |
| 511 |
| 512 InstructionOperand* outputs[1]; |
| 513 outputs[0] = g.DefineAsRegister(result); |
| 514 |
| 515 InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea; |
| 516 |
| 517 selector->Emit(opcode, 1, outputs, input_count, inputs); |
| 518 } |
| 519 |
| 520 } // namespace |
| 521 |
| 522 |
| 669 void InstructionSelector::VisitWord32Shl(Node* node) { | 523 void InstructionSelector::VisitWord32Shl(Node* node) { |
| 524 Int32ScaleMatcher m(node, true); |
| 525 if (m.matches()) { |
| 526 Node* index = node->InputAt(0); |
| 527 Node* base = m.power_of_two_plus_one() ? index : NULL; |
| 528 EmitLea(this, node, index, m.scale(), base, NULL); |
| 529 return; |
| 530 } |
| 670 VisitShift(this, node, kIA32Shl); | 531 VisitShift(this, node, kIA32Shl); |
| 671 } | 532 } |
| 672 | 533 |
| 673 | 534 |
| 674 void InstructionSelector::VisitWord32Shr(Node* node) { | 535 void InstructionSelector::VisitWord32Shr(Node* node) { |
| 675 VisitShift(this, node, kIA32Shr); | 536 VisitShift(this, node, kIA32Shr); |
| 676 } | 537 } |
| 677 | 538 |
| 678 | 539 |
| 679 void InstructionSelector::VisitWord32Sar(Node* node) { | 540 void InstructionSelector::VisitWord32Sar(Node* node) { |
| 680 VisitShift(this, node, kIA32Sar); | 541 VisitShift(this, node, kIA32Sar); |
| 681 } | 542 } |
| 682 | 543 |
| 683 | 544 |
| 684 void InstructionSelector::VisitWord32Ror(Node* node) { | 545 void InstructionSelector::VisitWord32Ror(Node* node) { |
| 685 VisitShift(this, node, kIA32Ror); | 546 VisitShift(this, node, kIA32Ror); |
| 686 } | 547 } |
| 687 | 548 |
| 688 | 549 |
| 689 static bool TryEmitLeaMultAdd(InstructionSelector* selector, Node* node) { | |
| 690 Int32BinopMatcher m(node); | |
| 691 if (!m.right().HasValue()) return false; | |
| 692 int32_t displacement_value = m.right().Value(); | |
| 693 Node* left = m.left().node(); | |
| 694 LeaMultiplyMatcher lmm(left); | |
| 695 if (!lmm.Matches()) return false; | |
| 696 AddressingMode mode; | |
| 697 size_t input_count; | |
| 698 IA32OperandGenerator g(selector); | |
| 699 InstructionOperand* index = g.UseRegister(lmm.Left()); | |
| 700 InstructionOperand* displacement = g.TempImmediate(displacement_value); | |
| 701 InstructionOperand* inputs[] = {index, displacement, displacement}; | |
| 702 if (lmm.Displacement() != 0) { | |
| 703 input_count = 3; | |
| 704 inputs[1] = index; | |
| 705 mode = kMode_MR1I; | |
| 706 } else { | |
| 707 input_count = 2; | |
| 708 mode = kMode_M1I; | |
| 709 } | |
| 710 mode = AdjustAddressingMode(mode, lmm.Power()); | |
| 711 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; | |
| 712 selector->Emit(kIA32Lea | AddressingModeField::encode(mode), 1, outputs, | |
| 713 input_count, inputs); | |
| 714 return true; | |
| 715 } | |
| 716 | |
| 717 | |
| 718 void InstructionSelector::VisitInt32Add(Node* node) { | 550 void InstructionSelector::VisitInt32Add(Node* node) { |
| 719 if (TryEmitLeaMultAdd(this, node)) return; | 551 IA32OperandGenerator g(this); |
| 552 |
| 553 // Try to match the Add to a lea pattern |
| 554 BaseWithIndexAndDisplacement32Matcher m(node); |
| 555 if (m.matches() && |
| 556 (m.displacement() == NULL || g.CanBeImmediate(m.displacement()))) { |
| 557 InstructionOperand* inputs[4]; |
| 558 size_t input_count = 0; |
| 559 AddressingMode mode = g.GenerateMemoryOperandInputs( |
| 560 m.index(), m.scale(), m.base(), m.displacement(), inputs, &input_count); |
| 561 |
| 562 DCHECK_NE(0, static_cast<int>(input_count)); |
| 563 DCHECK_GE(arraysize(inputs), input_count); |
| 564 |
| 565 InstructionOperand* outputs[1]; |
| 566 outputs[0] = g.DefineAsRegister(node); |
| 567 |
| 568 InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea; |
| 569 Emit(opcode, 1, outputs, input_count, inputs); |
| 570 return; |
| 571 } |
| 572 |
| 573 // No lea pattern match, use add |
| 720 VisitBinop(this, node, kIA32Add); | 574 VisitBinop(this, node, kIA32Add); |
| 721 } | 575 } |
| 722 | 576 |
| 723 | 577 |
| 724 void InstructionSelector::VisitInt32Sub(Node* node) { | 578 void InstructionSelector::VisitInt32Sub(Node* node) { |
| 725 IA32OperandGenerator g(this); | 579 IA32OperandGenerator g(this); |
| 726 Int32BinopMatcher m(node); | 580 Int32BinopMatcher m(node); |
| 727 if (m.left().Is(0)) { | 581 if (m.left().Is(0)) { |
| 728 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); | 582 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); |
| 729 } else { | 583 } else { |
| 730 VisitBinop(this, node, kIA32Sub); | 584 VisitBinop(this, node, kIA32Sub); |
| 731 } | 585 } |
| 732 } | 586 } |
| 733 | 587 |
| 734 | 588 |
| 735 static bool TryEmitLeaMult(InstructionSelector* selector, Node* node) { | |
| 736 LeaMultiplyMatcher lea(node); | |
| 737 // Try to match lea. | |
| 738 if (!lea.Matches()) return false; | |
| 739 AddressingMode mode; | |
| 740 size_t input_count; | |
| 741 IA32OperandGenerator g(selector); | |
| 742 InstructionOperand* left = g.UseRegister(lea.Left()); | |
| 743 InstructionOperand* inputs[] = {left, left}; | |
| 744 if (lea.Displacement() != 0) { | |
| 745 input_count = 2; | |
| 746 mode = kMode_MR1; | |
| 747 } else { | |
| 748 input_count = 1; | |
| 749 mode = kMode_M1; | |
| 750 } | |
| 751 mode = AdjustAddressingMode(mode, lea.Power()); | |
| 752 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; | |
| 753 selector->Emit(kIA32Lea | AddressingModeField::encode(mode), 1, outputs, | |
| 754 input_count, inputs); | |
| 755 return true; | |
| 756 } | |
| 757 | |
| 758 | |
| 759 void InstructionSelector::VisitInt32Mul(Node* node) { | 589 void InstructionSelector::VisitInt32Mul(Node* node) { |
| 760 if (TryEmitLeaMult(this, node)) return; | 590 Int32ScaleMatcher m(node, true); |
| 591 if (m.matches()) { |
| 592 Node* index = node->InputAt(0); |
| 593 Node* base = m.power_of_two_plus_one() ? index : NULL; |
| 594 EmitLea(this, node, index, m.scale(), base, NULL); |
| 595 return; |
| 596 } |
| 761 IA32OperandGenerator g(this); | 597 IA32OperandGenerator g(this); |
| 762 Int32BinopMatcher m(node); | 598 Node* left = node->InputAt(0); |
| 763 Node* left = m.left().node(); | 599 Node* right = node->InputAt(1); |
| 764 Node* right = m.right().node(); | |
| 765 if (g.CanBeImmediate(right)) { | 600 if (g.CanBeImmediate(right)) { |
| 766 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), | 601 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), |
| 767 g.UseImmediate(right)); | 602 g.UseImmediate(right)); |
| 768 } else { | 603 } else { |
| 769 if (g.CanBeBetterLeftOperand(right)) { | 604 if (g.CanBeBetterLeftOperand(right)) { |
| 770 std::swap(left, right); | 605 std::swap(left, right); |
| 771 } | 606 } |
| 772 Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), | 607 Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 773 g.Use(right)); | 608 g.Use(right)); |
| 774 } | 609 } |
| 775 } | 610 } |
| 776 | 611 |
| 777 | 612 |
| 778 namespace { | |
| 779 | |
| 780 void VisitMulHigh(InstructionSelector* selector, Node* node, | |
| 781 ArchOpcode opcode) { | |
| 782 IA32OperandGenerator g(selector); | |
| 783 selector->Emit(opcode, g.DefineAsFixed(node, edx), | |
| 784 g.UseFixed(node->InputAt(0), eax), | |
| 785 g.UseUniqueRegister(node->InputAt(1))); | |
| 786 } | |
| 787 | |
| 788 | |
| 789 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | |
| 790 IA32OperandGenerator g(selector); | |
| 791 InstructionOperand* temps[] = {g.TempRegister(edx)}; | |
| 792 selector->Emit(opcode, g.DefineAsFixed(node, eax), | |
| 793 g.UseFixed(node->InputAt(0), eax), | |
| 794 g.UseUnique(node->InputAt(1)), arraysize(temps), temps); | |
| 795 } | |
| 796 | |
| 797 | |
| 798 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | |
| 799 IA32OperandGenerator g(selector); | |
| 800 selector->Emit(opcode, g.DefineAsFixed(node, edx), | |
| 801 g.UseFixed(node->InputAt(0), eax), | |
| 802 g.UseUnique(node->InputAt(1))); | |
| 803 } | |
| 804 | |
| 805 } // namespace | |
| 806 | |
| 807 | |
| 808 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 613 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
| 809 VisitMulHigh(this, node, kIA32ImulHigh); | 614 VisitMulHigh(this, node, kIA32ImulHigh); |
| 810 } | 615 } |
| 811 | 616 |
| 812 | 617 |
| 813 void InstructionSelector::VisitUint32MulHigh(Node* node) { | 618 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
| 814 VisitMulHigh(this, node, kIA32UmulHigh); | 619 VisitMulHigh(this, node, kIA32UmulHigh); |
| 815 } | 620 } |
| 816 | 621 |
| 817 | 622 |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1242 return MachineOperatorBuilder::kFloat64Floor | | 1047 return MachineOperatorBuilder::kFloat64Floor | |
| 1243 MachineOperatorBuilder::kFloat64Ceil | | 1048 MachineOperatorBuilder::kFloat64Ceil | |
| 1244 MachineOperatorBuilder::kFloat64RoundTruncate | | 1049 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1245 MachineOperatorBuilder::kWord32ShiftIsSafe; | 1050 MachineOperatorBuilder::kWord32ShiftIsSafe; |
| 1246 } | 1051 } |
| 1247 return MachineOperatorBuilder::Flag::kNoFlags; | 1052 return MachineOperatorBuilder::Flag::kNoFlags; |
| 1248 } | 1053 } |
| 1249 } // namespace compiler | 1054 } // namespace compiler |
| 1250 } // namespace internal | 1055 } // namespace internal |
| 1251 } // namespace v8 | 1056 } // namespace v8 |
| OLD | NEW |