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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 } | 135 } |
136 } | 136 } |
137 | 137 |
138 | 138 |
139 static void VisitBinop(InstructionSelector* selector, Node* node, | 139 static void VisitBinop(InstructionSelector* selector, Node* node, |
140 InstructionCode opcode) { | 140 InstructionCode opcode) { |
141 FlagsContinuation cont; | 141 FlagsContinuation cont; |
142 VisitBinop(selector, node, opcode, &cont); | 142 VisitBinop(selector, node, opcode, &cont); |
143 } | 143 } |
144 | 144 |
| 145 void EmitLoad(InstructionSelector* selector, Node* node, InstructionCode opcode, |
| 146 Node* output = nullptr) { |
| 147 Mips64OperandGenerator g(selector); |
| 148 Node* base = node->InputAt(0); |
| 149 Node* index = node->InputAt(1); |
| 150 |
| 151 if (g.CanBeImmediate(index, opcode)) { |
| 152 selector->Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 153 g.DefineAsRegister(output == nullptr ? node : output), |
| 154 g.UseRegister(base), g.UseImmediate(index)); |
| 155 } else { |
| 156 InstructionOperand addr_reg = g.TempRegister(); |
| 157 selector->Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), |
| 158 addr_reg, g.UseRegister(index), g.UseRegister(base)); |
| 159 // Emit desired load opcode, using temp addr_reg. |
| 160 selector->Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 161 g.DefineAsRegister(output == nullptr ? node : output), |
| 162 addr_reg, g.TempImmediate(0)); |
| 163 } |
| 164 } |
145 | 165 |
146 void InstructionSelector::VisitLoad(Node* node) { | 166 void InstructionSelector::VisitLoad(Node* node) { |
147 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); | 167 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
148 Mips64OperandGenerator g(this); | |
149 Node* base = node->InputAt(0); | |
150 Node* index = node->InputAt(1); | |
151 | 168 |
152 ArchOpcode opcode = kArchNop; | 169 ArchOpcode opcode = kArchNop; |
153 switch (load_rep.representation()) { | 170 switch (load_rep.representation()) { |
154 case MachineRepresentation::kFloat32: | 171 case MachineRepresentation::kFloat32: |
155 opcode = kMips64Lwc1; | 172 opcode = kMips64Lwc1; |
156 break; | 173 break; |
157 case MachineRepresentation::kFloat64: | 174 case MachineRepresentation::kFloat64: |
158 opcode = kMips64Ldc1; | 175 opcode = kMips64Ldc1; |
159 break; | 176 break; |
160 case MachineRepresentation::kBit: // Fall through. | 177 case MachineRepresentation::kBit: // Fall through. |
(...skipping 11 matching lines...) Expand all Loading... |
172 case MachineRepresentation::kTagged: // Fall through. | 189 case MachineRepresentation::kTagged: // Fall through. |
173 case MachineRepresentation::kWord64: | 190 case MachineRepresentation::kWord64: |
174 opcode = kMips64Ld; | 191 opcode = kMips64Ld; |
175 break; | 192 break; |
176 case MachineRepresentation::kSimd128: // Fall through. | 193 case MachineRepresentation::kSimd128: // Fall through. |
177 case MachineRepresentation::kNone: | 194 case MachineRepresentation::kNone: |
178 UNREACHABLE(); | 195 UNREACHABLE(); |
179 return; | 196 return; |
180 } | 197 } |
181 | 198 |
182 if (g.CanBeImmediate(index, opcode)) { | 199 EmitLoad(this, node, opcode); |
183 Emit(opcode | AddressingModeField::encode(kMode_MRI), | |
184 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | |
185 } else { | |
186 InstructionOperand addr_reg = g.TempRegister(); | |
187 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, | |
188 g.UseRegister(index), g.UseRegister(base)); | |
189 // Emit desired load opcode, using temp addr_reg. | |
190 Emit(opcode | AddressingModeField::encode(kMode_MRI), | |
191 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); | |
192 } | |
193 } | 200 } |
194 | 201 |
195 | 202 |
196 void InstructionSelector::VisitStore(Node* node) { | 203 void InstructionSelector::VisitStore(Node* node) { |
197 Mips64OperandGenerator g(this); | 204 Mips64OperandGenerator g(this); |
198 Node* base = node->InputAt(0); | 205 Node* base = node->InputAt(0); |
199 Node* index = node->InputAt(1); | 206 Node* index = node->InputAt(1); |
200 Node* value = node->InputAt(2); | 207 Node* value = node->InputAt(2); |
201 | 208 |
202 StoreRepresentation store_rep = StoreRepresentationOf(node->op()); | 209 StoreRepresentation store_rep = StoreRepresentationOf(node->op()); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 | 501 |
495 void InstructionSelector::VisitWord32Sar(Node* node) { | 502 void InstructionSelector::VisitWord32Sar(Node* node) { |
496 VisitRRO(this, kMips64Sar, node); | 503 VisitRRO(this, kMips64Sar, node); |
497 } | 504 } |
498 | 505 |
499 | 506 |
500 void InstructionSelector::VisitWord64Shl(Node* node) { | 507 void InstructionSelector::VisitWord64Shl(Node* node) { |
501 Mips64OperandGenerator g(this); | 508 Mips64OperandGenerator g(this); |
502 Int64BinopMatcher m(node); | 509 Int64BinopMatcher m(node); |
503 if ((m.left().IsChangeInt32ToInt64() || m.left().IsChangeUint32ToUint64()) && | 510 if ((m.left().IsChangeInt32ToInt64() || m.left().IsChangeUint32ToUint64()) && |
504 m.right().IsInRange(32, 63)) { | 511 m.right().IsInRange(32, 63) && CanCover(node, m.left().node())) { |
505 // There's no need to sign/zero-extend to 64-bit if we shift out the upper | 512 // There's no need to sign/zero-extend to 64-bit if we shift out the upper |
506 // 32 bits anyway. | 513 // 32 bits anyway. |
507 Emit(kMips64Dshl, g.DefineSameAsFirst(node), | 514 Emit(kMips64Dshl, g.DefineSameAsFirst(node), |
508 g.UseRegister(m.left().node()->InputAt(0)), | 515 g.UseRegister(m.left().node()->InputAt(0)), |
509 g.UseImmediate(m.right().node())); | 516 g.UseImmediate(m.right().node())); |
510 return; | 517 return; |
511 } | 518 } |
512 if (m.left().IsWord64And() && CanCover(node, m.left().node()) && | 519 if (m.left().IsWord64And() && CanCover(node, m.left().node()) && |
513 m.right().IsInRange(1, 63)) { | 520 m.right().IsInRange(1, 63)) { |
514 // Match Word64Shl(Word64And(x, mask), imm) to Dshl where the mask is | 521 // Match Word64Shl(Word64And(x, mask), imm) to Dshl where the mask is |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1057 Node* success_output = NodeProperties::FindProjection(node, 1); | 1064 Node* success_output = NodeProperties::FindProjection(node, 1); |
1058 if (success_output) { | 1065 if (success_output) { |
1059 outputs[output_count++] = g.DefineAsRegister(success_output); | 1066 outputs[output_count++] = g.DefineAsRegister(success_output); |
1060 } | 1067 } |
1061 | 1068 |
1062 Emit(kMips64TruncUlD, output_count, outputs, 1, inputs); | 1069 Emit(kMips64TruncUlD, output_count, outputs, 1, inputs); |
1063 } | 1070 } |
1064 | 1071 |
1065 | 1072 |
1066 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { | 1073 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { |
1067 Mips64OperandGenerator g(this); | 1074 Node* value = node->InputAt(0); |
1068 Emit(kMips64Shl, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)), | 1075 if (value->opcode() == IrOpcode::kLoad && CanCover(node, value)) { |
1069 g.TempImmediate(0)); | 1076 // Generate sign-extending load. |
| 1077 LoadRepresentation load_rep = LoadRepresentationOf(value->op()); |
| 1078 InstructionCode opcode = kArchNop; |
| 1079 switch (load_rep.representation()) { |
| 1080 case MachineRepresentation::kBit: // Fall through. |
| 1081 case MachineRepresentation::kWord8: |
| 1082 opcode = load_rep.IsUnsigned() ? kMips64Lbu : kMips64Lb; |
| 1083 break; |
| 1084 case MachineRepresentation::kWord16: |
| 1085 opcode = load_rep.IsUnsigned() ? kMips64Lhu : kMips64Lh; |
| 1086 break; |
| 1087 case MachineRepresentation::kWord32: |
| 1088 opcode = kMips64Lw; |
| 1089 break; |
| 1090 default: |
| 1091 UNREACHABLE(); |
| 1092 return; |
| 1093 } |
| 1094 EmitLoad(this, value, opcode, node); |
| 1095 } else { |
| 1096 Mips64OperandGenerator g(this); |
| 1097 Emit(kMips64Shl, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)), |
| 1098 g.TempImmediate(0)); |
| 1099 } |
1070 } | 1100 } |
1071 | 1101 |
1072 | 1102 |
1073 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { | 1103 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { |
1074 Mips64OperandGenerator g(this); | 1104 Mips64OperandGenerator g(this); |
1075 Emit(kMips64Dext, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)), | 1105 Emit(kMips64Dext, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)), |
1076 g.TempImmediate(0), g.TempImmediate(32)); | 1106 g.TempImmediate(0), g.TempImmediate(32)); |
1077 } | 1107 } |
1078 | 1108 |
1079 | 1109 |
(...skipping 1079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2159 } else { | 2189 } else { |
2160 DCHECK(kArchVariant == kMips64r2); | 2190 DCHECK(kArchVariant == kMips64r2); |
2161 return MachineOperatorBuilder::AlignmentRequirements:: | 2191 return MachineOperatorBuilder::AlignmentRequirements:: |
2162 NoUnalignedAccessSupport(); | 2192 NoUnalignedAccessSupport(); |
2163 } | 2193 } |
2164 } | 2194 } |
2165 | 2195 |
2166 } // namespace compiler | 2196 } // namespace compiler |
2167 } // namespace internal | 2197 } // namespace internal |
2168 } // namespace v8 | 2198 } // namespace v8 |
OLD | NEW |