Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/compiler/arm/instruction-selector-arm.cc

Issue 719713002: [arm] Remove code duplication in instruction selector. Refactoring. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/bits.h" 5 #include "src/base/bits.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 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
11 namespace compiler { 11 namespace compiler {
12 12
13 // Adds Arm-specific methods for generating InstructionOperands. 13 // Adds Arm-specific methods for generating InstructionOperands.
14 class ArmOperandGenerator : public OperandGenerator { 14 class ArmOperandGenerator : public OperandGenerator {
15 public: 15 public:
16 explicit ArmOperandGenerator(InstructionSelector* selector) 16 explicit ArmOperandGenerator(InstructionSelector* selector)
17 : OperandGenerator(selector) {} 17 : OperandGenerator(selector) {}
18 18
19 InstructionOperand* UseOperand(Node* node, InstructionCode opcode) {
20 if (CanBeImmediate(node, opcode)) {
21 return UseImmediate(node);
22 }
23 return UseRegister(node);
24 }
25
26 bool CanBeImmediate(int32_t value) const { 19 bool CanBeImmediate(int32_t value) const {
27 return Assembler::ImmediateFitsAddrMode1Instruction(value); 20 return Assembler::ImmediateFitsAddrMode1Instruction(value);
28 } 21 }
29 22
30 bool CanBeImmediate(uint32_t value) const { 23 bool CanBeImmediate(uint32_t value) const {
31 return CanBeImmediate(bit_cast<int32_t>(value)); 24 return CanBeImmediate(bit_cast<int32_t>(value));
32 } 25 }
33 26
34 bool CanBeImmediate(Node* node, InstructionCode opcode) { 27 bool CanBeImmediate(Node* node, InstructionCode opcode) {
35 Int32Matcher m(node); 28 Int32Matcher m(node);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 case kArmLdr: 60 case kArmLdr:
68 case kArmStr: 61 case kArmStr:
69 case kArmStoreWriteBarrier: 62 case kArmStoreWriteBarrier:
70 return value >= -4095 && value <= 4095; 63 return value >= -4095 && value <= 4095;
71 64
72 case kArmLdrh: 65 case kArmLdrh:
73 case kArmLdrsh: 66 case kArmLdrsh:
74 case kArmStrh: 67 case kArmStrh:
75 return value >= -255 && value <= 255; 68 return value >= -255 && value <= 255;
76 69
77 case kArchCallCodeObject: 70 default:
78 case kArchCallJSFunction: 71 break;
79 case kArchJmp:
80 case kArchNop:
81 case kArchRet:
82 case kArchStackPointer:
83 case kArchTruncateDoubleToI:
84 case kArmMul:
85 case kArmMla:
86 case kArmMls:
87 case kArmSmmul:
88 case kArmSmmla:
89 case kArmUmull:
90 case kArmSdiv:
91 case kArmUdiv:
92 case kArmBfc:
93 case kArmUbfx:
94 case kArmSxtb:
95 case kArmSxth:
96 case kArmSxtab:
97 case kArmSxtah:
98 case kArmUxtb:
99 case kArmUxth:
100 case kArmUxtab:
101 case kArmUxtah:
102 case kArmVcmpF64:
103 case kArmVaddF64:
104 case kArmVsubF64:
105 case kArmVmulF64:
106 case kArmVmlaF64:
107 case kArmVmlsF64:
108 case kArmVdivF64:
109 case kArmVmodF64:
110 case kArmVnegF64:
111 case kArmVsqrtF64:
112 case kArmVfloorF64:
113 case kArmVceilF64:
114 case kArmVroundTruncateF64:
115 case kArmVroundTiesAwayF64:
116 case kArmVcvtF32F64:
117 case kArmVcvtF64F32:
118 case kArmVcvtF64S32:
119 case kArmVcvtF64U32:
120 case kArmVcvtS32F64:
121 case kArmVcvtU32F64:
122 case kArmPush:
123 return false;
124 } 72 }
125 UNREACHABLE();
126 return false; 73 return false;
127 } 74 }
128 }; 75 };
129 76
130 77
131 static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, 78 namespace {
132 Node* node) { 79
80 void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode,
81 Node* node) {
133 ArmOperandGenerator g(selector); 82 ArmOperandGenerator g(selector);
134 selector->Emit(opcode, g.DefineAsRegister(node), 83 selector->Emit(opcode, g.DefineAsRegister(node),
135 g.UseRegister(node->InputAt(0))); 84 g.UseRegister(node->InputAt(0)));
136 } 85 }
137 86
138 87
139 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, 88 void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode,
140 Node* node) { 89 Node* node) {
141 ArmOperandGenerator g(selector); 90 ArmOperandGenerator g(selector);
142 selector->Emit(opcode, g.DefineAsRegister(node), 91 selector->Emit(opcode, g.DefineAsRegister(node),
143 g.UseRegister(node->InputAt(0)), 92 g.UseRegister(node->InputAt(0)),
144 g.UseRegister(node->InputAt(1))); 93 g.UseRegister(node->InputAt(1)));
145 } 94 }
146 95
147 96
148 static bool TryMatchROR(InstructionSelector* selector, 97 template <IrOpcode::Value kOpcode, int kImmMin, int kImmMax,
149 InstructionCode* opcode_return, Node* node, 98 AddressingMode kImmMode, AddressingMode kRegMode>
150 InstructionOperand** value_return, 99 bool TryMatchShift(InstructionSelector* selector,
151 InstructionOperand** shift_return) { 100 InstructionCode* opcode_return, Node* node,
101 InstructionOperand** value_return,
102 InstructionOperand** shift_return) {
152 ArmOperandGenerator g(selector); 103 ArmOperandGenerator g(selector);
153 if (node->opcode() != IrOpcode::kWord32Ror) return false; 104 if (node->opcode() == kOpcode) {
154 Int32BinopMatcher m(node); 105 Int32BinopMatcher m(node);
155 *value_return = g.UseRegister(m.left().node()); 106 *value_return = g.UseRegister(m.left().node());
156 if (m.right().IsInRange(1, 31)) { 107 if (m.right().IsInRange(kImmMin, kImmMax)) {
157 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_I); 108 *opcode_return |= AddressingModeField::encode(kImmMode);
158 *shift_return = g.UseImmediate(m.right().node()); 109 *shift_return = g.UseImmediate(m.right().node());
159 } else { 110 } else {
160 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_R); 111 *opcode_return |= AddressingModeField::encode(kRegMode);
161 *shift_return = g.UseRegister(m.right().node()); 112 *shift_return = g.UseRegister(m.right().node());
113 }
114 return true;
162 } 115 }
163 return true; 116 return false;
164 } 117 }
165 118
166 119
167 static inline bool TryMatchASR(InstructionSelector* selector, 120 bool TryMatchROR(InstructionSelector* selector, InstructionCode* opcode_return,
168 InstructionCode* opcode_return, Node* node, 121 Node* node, InstructionOperand** value_return,
169 InstructionOperand** value_return, 122 InstructionOperand** shift_return) {
170 InstructionOperand** shift_return) { 123 return TryMatchShift<IrOpcode::kWord32Ror, 1, 31, kMode_Operand2_R_ROR_I,
171 ArmOperandGenerator g(selector); 124 kMode_Operand2_R_ROR_R>(selector, opcode_return, node,
172 if (node->opcode() != IrOpcode::kWord32Sar) return false; 125 value_return, shift_return);
173 Int32BinopMatcher m(node);
174 *value_return = g.UseRegister(m.left().node());
175 if (m.right().IsInRange(1, 32)) {
176 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_I);
177 *shift_return = g.UseImmediate(m.right().node());
178 } else {
179 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_R);
180 *shift_return = g.UseRegister(m.right().node());
181 }
182 return true;
183 } 126 }
184 127
185 128
186 static inline bool TryMatchLSL(InstructionSelector* selector, 129 bool TryMatchASR(InstructionSelector* selector, InstructionCode* opcode_return,
187 InstructionCode* opcode_return, Node* node, 130 Node* node, InstructionOperand** value_return,
188 InstructionOperand** value_return, 131 InstructionOperand** shift_return) {
189 InstructionOperand** shift_return) { 132 return TryMatchShift<IrOpcode::kWord32Sar, 1, 32, kMode_Operand2_R_ASR_I,
190 ArmOperandGenerator g(selector); 133 kMode_Operand2_R_ASR_R>(selector, opcode_return, node,
191 if (node->opcode() != IrOpcode::kWord32Shl) return false; 134 value_return, shift_return);
192 Int32BinopMatcher m(node);
193 *value_return = g.UseRegister(m.left().node());
194 if (m.right().IsInRange(0, 31)) {
195 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
196 *shift_return = g.UseImmediate(m.right().node());
197 } else {
198 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_R);
199 *shift_return = g.UseRegister(m.right().node());
200 }
201 return true;
202 } 135 }
203 136
204 137
205 static inline bool TryMatchLSR(InstructionSelector* selector, 138 bool TryMatchLSL(InstructionSelector* selector, InstructionCode* opcode_return,
206 InstructionCode* opcode_return, Node* node, 139 Node* node, InstructionOperand** value_return,
207 InstructionOperand** value_return, 140 InstructionOperand** shift_return) {
208 InstructionOperand** shift_return) { 141 return TryMatchShift<IrOpcode::kWord32Shl, 0, 31, kMode_Operand2_R_LSL_I,
209 ArmOperandGenerator g(selector); 142 kMode_Operand2_R_LSL_R>(selector, opcode_return, node,
210 if (node->opcode() != IrOpcode::kWord32Shr) return false; 143 value_return, shift_return);
211 Int32BinopMatcher m(node);
212 *value_return = g.UseRegister(m.left().node());
213 if (m.right().IsInRange(1, 32)) {
214 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_I);
215 *shift_return = g.UseImmediate(m.right().node());
216 } else {
217 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_R);
218 *shift_return = g.UseRegister(m.right().node());
219 }
220 return true;
221 } 144 }
222 145
223 146
224 static inline bool TryMatchShift(InstructionSelector* selector, 147 bool TryMatchLSR(InstructionSelector* selector, InstructionCode* opcode_return,
225 InstructionCode* opcode_return, Node* node, 148 Node* node, InstructionOperand** value_return,
226 InstructionOperand** value_return, 149 InstructionOperand** shift_return) {
227 InstructionOperand** shift_return) { 150 return TryMatchShift<IrOpcode::kWord32Shr, 1, 32, kMode_Operand2_R_LSR_I,
151 kMode_Operand2_R_LSR_R>(selector, opcode_return, node,
152 value_return, shift_return);
153 }
154
155
156 bool TryMatchShift(InstructionSelector* selector,
157 InstructionCode* opcode_return, Node* node,
158 InstructionOperand** value_return,
159 InstructionOperand** shift_return) {
228 return ( 160 return (
229 TryMatchASR(selector, opcode_return, node, value_return, shift_return) || 161 TryMatchASR(selector, opcode_return, node, value_return, shift_return) ||
230 TryMatchLSL(selector, opcode_return, node, value_return, shift_return) || 162 TryMatchLSL(selector, opcode_return, node, value_return, shift_return) ||
231 TryMatchLSR(selector, opcode_return, node, value_return, shift_return) || 163 TryMatchLSR(selector, opcode_return, node, value_return, shift_return) ||
232 TryMatchROR(selector, opcode_return, node, value_return, shift_return)); 164 TryMatchROR(selector, opcode_return, node, value_return, shift_return));
233 } 165 }
234 166
235 167
236 static inline bool TryMatchImmediateOrShift(InstructionSelector* selector, 168 bool TryMatchImmediateOrShift(InstructionSelector* selector,
237 InstructionCode* opcode_return, 169 InstructionCode* opcode_return, Node* node,
238 Node* node, 170 size_t* input_count_return,
239 size_t* input_count_return, 171 InstructionOperand** inputs) {
240 InstructionOperand** inputs) {
241 ArmOperandGenerator g(selector); 172 ArmOperandGenerator g(selector);
242 if (g.CanBeImmediate(node, *opcode_return)) { 173 if (g.CanBeImmediate(node, *opcode_return)) {
243 *opcode_return |= AddressingModeField::encode(kMode_Operand2_I); 174 *opcode_return |= AddressingModeField::encode(kMode_Operand2_I);
244 inputs[0] = g.UseImmediate(node); 175 inputs[0] = g.UseImmediate(node);
245 *input_count_return = 1; 176 *input_count_return = 1;
246 return true; 177 return true;
247 } 178 }
248 if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) { 179 if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) {
249 *input_count_return = 2; 180 *input_count_return = 2;
250 return true; 181 return true;
251 } 182 }
252 return false; 183 return false;
253 } 184 }
254 185
255 186
256 static void VisitBinop(InstructionSelector* selector, Node* node, 187 void VisitBinop(InstructionSelector* selector, Node* node,
257 InstructionCode opcode, InstructionCode reverse_opcode, 188 InstructionCode opcode, InstructionCode reverse_opcode,
258 FlagsContinuation* cont) { 189 FlagsContinuation* cont) {
259 ArmOperandGenerator g(selector); 190 ArmOperandGenerator g(selector);
260 Int32BinopMatcher m(node); 191 Int32BinopMatcher m(node);
261 InstructionOperand* inputs[5]; 192 InstructionOperand* inputs[5];
262 size_t input_count = 0; 193 size_t input_count = 0;
263 InstructionOperand* outputs[2]; 194 InstructionOperand* outputs[2];
264 size_t output_count = 0; 195 size_t output_count = 0;
265 196
266 if (m.left().node() == m.right().node()) { 197 if (m.left().node() == m.right().node()) {
267 // If both inputs refer to the same operand, enforce allocating a register 198 // If both inputs refer to the same operand, enforce allocating a register
268 // for both of them to ensure that we don't end up generating code like 199 // for both of them to ensure that we don't end up generating code like
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 DCHECK_GE(arraysize(inputs), input_count); 237 DCHECK_GE(arraysize(inputs), input_count);
307 DCHECK_GE(arraysize(outputs), output_count); 238 DCHECK_GE(arraysize(outputs), output_count);
308 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); 239 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode));
309 240
310 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, 241 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
311 outputs, input_count, inputs); 242 outputs, input_count, inputs);
312 if (cont->IsBranch()) instr->MarkAsControl(); 243 if (cont->IsBranch()) instr->MarkAsControl();
313 } 244 }
314 245
315 246
316 static void VisitBinop(InstructionSelector* selector, Node* node, 247 void VisitBinop(InstructionSelector* selector, Node* node,
317 InstructionCode opcode, InstructionCode reverse_opcode) { 248 InstructionCode opcode, InstructionCode reverse_opcode) {
318 FlagsContinuation cont; 249 FlagsContinuation cont;
319 VisitBinop(selector, node, opcode, reverse_opcode, &cont); 250 VisitBinop(selector, node, opcode, reverse_opcode, &cont);
320 } 251 }
321 252
322 253
254 } // namespace
255
256
323 void InstructionSelector::VisitLoad(Node* node) { 257 void InstructionSelector::VisitLoad(Node* node) {
324 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); 258 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
325 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); 259 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
326 ArmOperandGenerator g(this); 260 ArmOperandGenerator g(this);
327 Node* base = node->InputAt(0); 261 Node* base = node->InputAt(0);
328 Node* index = node->InputAt(1); 262 Node* index = node->InputAt(1);
329 263
330 ArchOpcode opcode; 264 ArchOpcode opcode;
331 switch (rep) { 265 switch (rep) {
332 case kRepFloat32: 266 case kRepFloat32:
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 if (g.CanBeImmediate(index, opcode)) { 343 if (g.CanBeImmediate(index, opcode)) {
410 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL, 344 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL,
411 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); 345 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
412 } else { 346 } else {
413 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL, 347 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL,
414 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); 348 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value));
415 } 349 }
416 } 350 }
417 351
418 352
419 static inline void EmitBic(InstructionSelector* selector, Node* node, 353 namespace {
420 Node* left, Node* right) { 354
355 void EmitBic(InstructionSelector* selector, Node* node, Node* left,
356 Node* right) {
421 ArmOperandGenerator g(selector); 357 ArmOperandGenerator g(selector);
422 InstructionCode opcode = kArmBic; 358 InstructionCode opcode = kArmBic;
423 InstructionOperand* value_operand; 359 InstructionOperand* value_operand;
424 InstructionOperand* shift_operand; 360 InstructionOperand* shift_operand;
425 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) { 361 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) {
426 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), 362 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
427 value_operand, shift_operand); 363 value_operand, shift_operand);
428 return; 364 return;
429 } 365 }
430 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), 366 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
431 g.DefineAsRegister(node), g.UseRegister(left), 367 g.DefineAsRegister(node), g.UseRegister(left),
432 g.UseRegister(right)); 368 g.UseRegister(right));
433 } 369 }
434 370
371 } // namespace
372
435 373
436 void InstructionSelector::VisitWord32And(Node* node) { 374 void InstructionSelector::VisitWord32And(Node* node) {
437 ArmOperandGenerator g(this); 375 ArmOperandGenerator g(this);
438 Int32BinopMatcher m(node); 376 Int32BinopMatcher m(node);
439 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) { 377 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) {
440 Int32BinopMatcher mleft(m.left().node()); 378 Int32BinopMatcher mleft(m.left().node());
441 if (mleft.right().Is(-1)) { 379 if (mleft.right().Is(-1)) {
442 EmitBic(this, node, m.right().node(), mleft.left().node()); 380 EmitBic(this, node, m.right().node(), mleft.left().node());
443 return; 381 return;
444 } 382 }
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 MachineOperatorBuilder::kFloat64Ceil | 1256 MachineOperatorBuilder::kFloat64Ceil |
1319 MachineOperatorBuilder::kFloat64RoundTruncate | 1257 MachineOperatorBuilder::kFloat64RoundTruncate |
1320 MachineOperatorBuilder::kFloat64RoundTiesAway; 1258 MachineOperatorBuilder::kFloat64RoundTiesAway;
1321 } 1259 }
1322 return flags; 1260 return flags;
1323 } 1261 }
1324 1262
1325 } // namespace compiler 1263 } // namespace compiler
1326 } // namespace internal 1264 } // namespace internal
1327 } // namespace v8 1265 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698