| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/base/adapters.h" | 5 #include "src/base/adapters.h" |
| 6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
| 7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 | 10 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 explicit Mips64OperandGenerator(InstructionSelector* selector) | 24 explicit Mips64OperandGenerator(InstructionSelector* selector) |
| 25 : OperandGenerator(selector) {} | 25 : OperandGenerator(selector) {} |
| 26 | 26 |
| 27 InstructionOperand UseOperand(Node* node, InstructionCode opcode) { | 27 InstructionOperand UseOperand(Node* node, InstructionCode opcode) { |
| 28 if (CanBeImmediate(node, opcode)) { | 28 if (CanBeImmediate(node, opcode)) { |
| 29 return UseImmediate(node); | 29 return UseImmediate(node); |
| 30 } | 30 } |
| 31 return UseRegister(node); | 31 return UseRegister(node); |
| 32 } | 32 } |
| 33 | 33 |
| 34 bool CanBeImmediate(Node* node, InstructionCode opcode) { | 34 bool IsIntegerConstant(Node* node) { |
| 35 int64_t value; | 35 return (node->opcode() == IrOpcode::kInt32Constant) || |
| 36 if (node->opcode() == IrOpcode::kInt32Constant) | 36 (node->opcode() == IrOpcode::kInt64Constant); |
| 37 value = OpParameter<int32_t>(node); | 37 } |
| 38 else if (node->opcode() == IrOpcode::kInt64Constant) | 38 |
| 39 value = OpParameter<int64_t>(node); | 39 int64_t GetIntegerConstantValue(Node* node) { |
| 40 else | 40 if (node->opcode() == IrOpcode::kInt32Constant) { |
| 41 return false; | 41 return OpParameter<int32_t>(node); |
| 42 } |
| 43 DCHECK(node->opcode() == IrOpcode::kInt64Constant); |
| 44 return OpParameter<int64_t>(node); |
| 45 } |
| 46 |
| 47 bool CanBeImmediate(Node* node, InstructionCode mode) { |
| 48 return IsIntegerConstant(node) && |
| 49 CanBeImmediate(GetIntegerConstantValue(node), mode); |
| 50 } |
| 51 |
| 52 bool CanBeImmediate(int64_t value, InstructionCode opcode) { |
| 42 switch (ArchOpcodeField::decode(opcode)) { | 53 switch (ArchOpcodeField::decode(opcode)) { |
| 43 case kMips64Shl: | 54 case kMips64Shl: |
| 44 case kMips64Sar: | 55 case kMips64Sar: |
| 45 case kMips64Shr: | 56 case kMips64Shr: |
| 46 return is_uint5(value); | 57 return is_uint5(value); |
| 47 case kMips64Dshl: | 58 case kMips64Dshl: |
| 48 case kMips64Dsar: | 59 case kMips64Dsar: |
| 49 case kMips64Dshr: | 60 case kMips64Dshr: |
| 50 return is_uint6(value); | 61 return is_uint6(value); |
| 51 case kMips64Xor: | 62 case kMips64Xor: |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 | 95 |
| 85 | 96 |
| 86 static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, | 97 static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, |
| 87 Node* node) { | 98 Node* node) { |
| 88 Mips64OperandGenerator g(selector); | 99 Mips64OperandGenerator g(selector); |
| 89 selector->Emit(opcode, g.DefineAsRegister(node), | 100 selector->Emit(opcode, g.DefineAsRegister(node), |
| 90 g.UseRegister(node->InputAt(0)), | 101 g.UseRegister(node->InputAt(0)), |
| 91 g.UseOperand(node->InputAt(1), opcode)); | 102 g.UseOperand(node->InputAt(1), opcode)); |
| 92 } | 103 } |
| 93 | 104 |
| 105 struct ExtendingLoadMatcher { |
| 106 ExtendingLoadMatcher(Node* node, InstructionSelector* selector) |
| 107 : matches_(false), selector_(selector), base_(nullptr), immediate_(0) { |
| 108 Initialize(node); |
| 109 } |
| 110 |
| 111 bool Matches() const { return matches_; } |
| 112 |
| 113 Node* base() const { |
| 114 DCHECK(Matches()); |
| 115 return base_; |
| 116 } |
| 117 int64_t immediate() const { |
| 118 DCHECK(Matches()); |
| 119 return immediate_; |
| 120 } |
| 121 ArchOpcode opcode() const { |
| 122 DCHECK(Matches()); |
| 123 return opcode_; |
| 124 } |
| 125 |
| 126 private: |
| 127 bool matches_; |
| 128 InstructionSelector* selector_; |
| 129 Node* base_; |
| 130 int64_t immediate_; |
| 131 ArchOpcode opcode_; |
| 132 |
| 133 void Initialize(Node* node) { |
| 134 Int64BinopMatcher m(node); |
| 135 // When loading a 64-bit value and shifting by 32, we should |
| 136 // just load and sign-extend the interesting 4 bytes instead. |
| 137 // This happens, for example, when we're loading and untagging SMIs. |
| 138 DCHECK(m.IsWord64Sar()); |
| 139 if (m.left().IsLoad() && m.right().Is(32) && |
| 140 selector_->CanCover(m.node(), m.left().node())) { |
| 141 Mips64OperandGenerator g(selector_); |
| 142 Node* load = m.left().node(); |
| 143 Node* offset = load->InputAt(1); |
| 144 base_ = load->InputAt(0); |
| 145 opcode_ = kMips64Lw; |
| 146 if (g.CanBeImmediate(offset, opcode_)) { |
| 147 #if defined(V8_TARGET_LITTLE_ENDIAN) |
| 148 immediate_ = g.GetIntegerConstantValue(offset) + 4; |
| 149 #elif defined(V8_TARGET_BIG_ENDIAN) |
| 150 immediate_ = g.GetIntegerConstantValue(offset); |
| 151 #endif |
| 152 matches_ = g.CanBeImmediate(immediate_, kMips64Lw); |
| 153 } |
| 154 } |
| 155 } |
| 156 }; |
| 157 |
| 158 bool TryEmitExtendingLoad(InstructionSelector* selector, Node* node) { |
| 159 ExtendingLoadMatcher m(node, selector); |
| 160 Mips64OperandGenerator g(selector); |
| 161 if (m.Matches()) { |
| 162 InstructionOperand inputs[2]; |
| 163 inputs[0] = g.UseRegister(m.base()); |
| 164 InstructionCode opcode = |
| 165 m.opcode() | AddressingModeField::encode(kMode_MRI); |
| 166 DCHECK(is_int32(m.immediate())); |
| 167 inputs[1] = g.TempImmediate(static_cast<int32_t>(m.immediate())); |
| 168 InstructionOperand outputs[] = {g.DefineAsRegister(node)}; |
| 169 selector->Emit(opcode, arraysize(outputs), outputs, arraysize(inputs), |
| 170 inputs); |
| 171 return true; |
| 172 } |
| 173 return false; |
| 174 } |
| 94 | 175 |
| 95 static void VisitBinop(InstructionSelector* selector, Node* node, | 176 static void VisitBinop(InstructionSelector* selector, Node* node, |
| 96 InstructionCode opcode, FlagsContinuation* cont) { | 177 InstructionCode opcode, FlagsContinuation* cont) { |
| 97 Mips64OperandGenerator g(selector); | 178 Mips64OperandGenerator g(selector); |
| 98 Int32BinopMatcher m(node); | 179 Int32BinopMatcher m(node); |
| 99 InstructionOperand inputs[4]; | 180 InstructionOperand inputs[4]; |
| 100 size_t input_count = 0; | 181 size_t input_count = 0; |
| 101 InstructionOperand outputs[2]; | 182 InstructionOperand outputs[2]; |
| 102 size_t output_count = 0; | 183 size_t output_count = 0; |
| 103 | 184 |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 g.TempImmediate(mask_width)); | 671 g.TempImmediate(mask_width)); |
| 591 return; | 672 return; |
| 592 } | 673 } |
| 593 } | 674 } |
| 594 } | 675 } |
| 595 VisitRRO(this, kMips64Dshr, node); | 676 VisitRRO(this, kMips64Dshr, node); |
| 596 } | 677 } |
| 597 | 678 |
| 598 | 679 |
| 599 void InstructionSelector::VisitWord64Sar(Node* node) { | 680 void InstructionSelector::VisitWord64Sar(Node* node) { |
| 681 if (TryEmitExtendingLoad(this, node)) return; |
| 600 VisitRRO(this, kMips64Dsar, node); | 682 VisitRRO(this, kMips64Dsar, node); |
| 601 } | 683 } |
| 602 | 684 |
| 603 | 685 |
| 604 void InstructionSelector::VisitWord32Ror(Node* node) { | 686 void InstructionSelector::VisitWord32Ror(Node* node) { |
| 605 VisitRRO(this, kMips64Ror, node); | 687 VisitRRO(this, kMips64Ror, node); |
| 606 } | 688 } |
| 607 | 689 |
| 608 | 690 |
| 609 void InstructionSelector::VisitWord32Clz(Node* node) { | 691 void InstructionSelector::VisitWord32Clz(Node* node) { |
| (...skipping 1800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2410 } else { | 2492 } else { |
| 2411 DCHECK(kArchVariant == kMips64r2); | 2493 DCHECK(kArchVariant == kMips64r2); |
| 2412 return MachineOperatorBuilder::AlignmentRequirements:: | 2494 return MachineOperatorBuilder::AlignmentRequirements:: |
| 2413 NoUnalignedAccessSupport(); | 2495 NoUnalignedAccessSupport(); |
| 2414 } | 2496 } |
| 2415 } | 2497 } |
| 2416 | 2498 |
| 2417 } // namespace compiler | 2499 } // namespace compiler |
| 2418 } // namespace internal | 2500 } // namespace internal |
| 2419 } // namespace v8 | 2501 } // namespace v8 |
| OLD | NEW |