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 |