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

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

Issue 415403005: [turbofan] Support for combining branches with <Operation>WithOverflow. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 months 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 | « src/compiler/arm64/instruction-selector-arm64.cc ('k') | src/compiler/instruction-selector.h » ('j') | 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/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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 } else { // store [%base + %index], %|#value 154 } else { // store [%base + %index], %|#value
155 Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL, 155 Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL,
156 g.UseRegister(base), g.UseRegister(index), val); 156 g.UseRegister(base), g.UseRegister(index), val);
157 } 157 }
158 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] 158 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
159 } 159 }
160 160
161 161
162 // Shared routine for multiple binary operations. 162 // Shared routine for multiple binary operations.
163 static void VisitBinop(InstructionSelector* selector, Node* node, 163 static void VisitBinop(InstructionSelector* selector, Node* node,
164 ArchOpcode opcode) { 164 InstructionCode opcode, FlagsContinuation* cont) {
165 IA32OperandGenerator g(selector); 165 IA32OperandGenerator g(selector);
166 Int32BinopMatcher m(node); 166 Int32BinopMatcher m(node);
167 // TODO(turbofan): match complex addressing modes. 167 InstructionOperand* inputs[4];
168 // TODO(turbofan): if commutative, pick the non-live-in operand as the left as
169 // this might be the last use and therefore its register can be reused.
170 if (g.CanBeImmediate(m.right().node())) {
171 selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(m.left().node()),
172 g.UseImmediate(m.right().node()));
173 } else {
174 selector->Emit(opcode, g.DefineSameAsFirst(node),
175 g.UseRegister(m.left().node()), g.Use(m.right().node()));
176 }
177 }
178
179
180 static void VisitBinopWithOverflow(InstructionSelector* selector, Node* node,
181 InstructionCode opcode) {
182 IA32OperandGenerator g(selector);
183 Int32BinopMatcher m(node);
184 InstructionOperand* inputs[2];
185 size_t input_count = 0; 168 size_t input_count = 0;
186 InstructionOperand* outputs[2]; 169 InstructionOperand* outputs[2];
187 size_t output_count = 0; 170 size_t output_count = 0;
188 171
189 // TODO(turbofan): match complex addressing modes. 172 // TODO(turbofan): match complex addressing modes.
190 // TODO(turbofan): if commutative, pick the non-live-in operand as the left as 173 // TODO(turbofan): if commutative, pick the non-live-in operand as the left as
191 // this might be the last use and therefore its register can be reused. 174 // this might be the last use and therefore its register can be reused.
192 if (g.CanBeImmediate(m.right().node())) { 175 if (g.CanBeImmediate(m.right().node())) {
193 inputs[input_count++] = g.Use(m.left().node()); 176 inputs[input_count++] = g.Use(m.left().node());
194 inputs[input_count++] = g.UseImmediate(m.right().node()); 177 inputs[input_count++] = g.UseImmediate(m.right().node());
195 } else { 178 } else {
196 inputs[input_count++] = g.UseRegister(m.left().node()); 179 inputs[input_count++] = g.UseRegister(m.left().node());
197 inputs[input_count++] = g.Use(m.right().node()); 180 inputs[input_count++] = g.Use(m.right().node());
198 } 181 }
199 182
200 // Define outputs depending on the projections. 183 if (cont->IsBranch()) {
201 Node* projections[2]; 184 inputs[input_count++] = g.Label(cont->true_block());
202 node->CollectProjections(ARRAY_SIZE(projections), projections); 185 inputs[input_count++] = g.Label(cont->false_block());
203 if (projections[0]) {
204 outputs[output_count++] = g.DefineSameAsFirst(projections[0]);
205 } 186 }
206 if (projections[1]) { 187
207 opcode |= FlagsModeField::encode(kFlags_set); 188 outputs[output_count++] = g.DefineSameAsFirst(node);
208 opcode |= FlagsConditionField::encode(kOverflow); 189 if (cont->IsSet()) {
209 // TODO(turbofan): Use byte register here. 190 // TODO(turbofan): Use byte register here.
210 outputs[output_count++] = 191 outputs[output_count++] = g.DefineAsRegister(cont->result());
211 (projections[0] ? g.DefineAsRegister(projections[1])
212 : g.DefineSameAsFirst(projections[1]));
213 } 192 }
214 193
215 ASSERT_NE(0, input_count); 194 ASSERT_NE(0, input_count);
216 ASSERT_NE(0, output_count); 195 ASSERT_NE(0, output_count);
217 ASSERT_GE(ARRAY_SIZE(inputs), input_count); 196 ASSERT_GE(ARRAY_SIZE(inputs), input_count);
218 ASSERT_GE(ARRAY_SIZE(outputs), output_count); 197 ASSERT_GE(ARRAY_SIZE(outputs), output_count);
219 198
220 selector->Emit(opcode, output_count, outputs, input_count, inputs); 199 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
200 outputs, input_count, inputs);
201 if (cont->IsBranch()) instr->MarkAsControl();
221 } 202 }
222 203
223 204
205 // Shared routine for multiple binary operations.
206 static void VisitBinop(InstructionSelector* selector, Node* node,
207 InstructionCode opcode) {
208 FlagsContinuation cont;
209 VisitBinop(selector, node, opcode, &cont);
210 }
211
212
224 void InstructionSelector::VisitWord32And(Node* node) { 213 void InstructionSelector::VisitWord32And(Node* node) {
225 VisitBinop(this, node, kIA32And); 214 VisitBinop(this, node, kIA32And);
226 } 215 }
227 216
228 217
229 void InstructionSelector::VisitWord32Or(Node* node) { 218 void InstructionSelector::VisitWord32Or(Node* node) {
230 VisitBinop(this, node, kIA32Or); 219 VisitBinop(this, node, kIA32Or);
231 } 220 }
232 221
233 222
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 void InstructionSelector::VisitWord32Sar(Node* node) { 269 void InstructionSelector::VisitWord32Sar(Node* node) {
281 VisitShift(this, node, kIA32Sar); 270 VisitShift(this, node, kIA32Sar);
282 } 271 }
283 272
284 273
285 void InstructionSelector::VisitInt32Add(Node* node) { 274 void InstructionSelector::VisitInt32Add(Node* node) {
286 VisitBinop(this, node, kIA32Add); 275 VisitBinop(this, node, kIA32Add);
287 } 276 }
288 277
289 278
290 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
291 VisitBinopWithOverflow(this, node, kIA32Add);
292 }
293
294
295 void InstructionSelector::VisitInt32Sub(Node* node) { 279 void InstructionSelector::VisitInt32Sub(Node* node) {
296 IA32OperandGenerator g(this); 280 IA32OperandGenerator g(this);
297 Int32BinopMatcher m(node); 281 Int32BinopMatcher m(node);
298 if (m.left().Is(0)) { 282 if (m.left().Is(0)) {
299 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); 283 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node()));
300 } else { 284 } else {
301 VisitBinop(this, node, kIA32Sub); 285 VisitBinop(this, node, kIA32Sub);
302 } 286 }
303 } 287 }
304 288
305 289
306 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
307 VisitBinopWithOverflow(this, node, kIA32Sub);
308 }
309
310
311 void InstructionSelector::VisitInt32Mul(Node* node) { 290 void InstructionSelector::VisitInt32Mul(Node* node) {
312 IA32OperandGenerator g(this); 291 IA32OperandGenerator g(this);
313 Node* left = node->InputAt(0); 292 Node* left = node->InputAt(0);
314 Node* right = node->InputAt(1); 293 Node* right = node->InputAt(1);
315 if (g.CanBeImmediate(right)) { 294 if (g.CanBeImmediate(right)) {
316 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), 295 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left),
317 g.UseImmediate(right)); 296 g.UseImmediate(right));
318 } else if (g.CanBeImmediate(left)) { 297 } else if (g.CanBeImmediate(left)) {
319 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(right), 298 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(right),
320 g.UseImmediate(left)); 299 g.UseImmediate(left));
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 410
432 void InstructionSelector::VisitFloat64Mod(Node* node) { 411 void InstructionSelector::VisitFloat64Mod(Node* node) {
433 IA32OperandGenerator g(this); 412 IA32OperandGenerator g(this);
434 InstructionOperand* temps[] = {g.TempRegister(eax)}; 413 InstructionOperand* temps[] = {g.TempRegister(eax)};
435 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), 414 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
436 g.UseDoubleRegister(node->InputAt(0)), 415 g.UseDoubleRegister(node->InputAt(0)),
437 g.UseDoubleRegister(node->InputAt(1)), 1, temps); 416 g.UseDoubleRegister(node->InputAt(1)), 1, temps);
438 } 417 }
439 418
440 419
420 void InstructionSelector::VisitInt32AddWithOverflow(Node* node,
421 FlagsContinuation* cont) {
422 VisitBinop(this, node, kIA32Add, cont);
423 }
424
425
426 void InstructionSelector::VisitInt32SubWithOverflow(Node* node,
427 FlagsContinuation* cont) {
428 VisitBinop(this, node, kIA32Sub, cont);
429 }
430
431
441 // Shared routine for multiple compare operations. 432 // Shared routine for multiple compare operations.
442 static inline void VisitCompare(InstructionSelector* selector, 433 static inline void VisitCompare(InstructionSelector* selector,
443 InstructionCode opcode, 434 InstructionCode opcode,
444 InstructionOperand* left, 435 InstructionOperand* left,
445 InstructionOperand* right, 436 InstructionOperand* right,
446 FlagsContinuation* cont) { 437 FlagsContinuation* cont) {
447 IA32OperandGenerator g(selector); 438 IA32OperandGenerator g(selector);
448 if (cont->IsBranch()) { 439 if (cont->IsBranch()) {
449 selector->Emit(cont->Encode(opcode), NULL, left, right, 440 selector->Emit(cont->Encode(opcode), NULL, left, right,
450 g.Label(cont->true_block()), 441 g.Label(cont->true_block()),
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 if (descriptor->kind() == CallDescriptor::kCallAddress && 551 if (descriptor->kind() == CallDescriptor::kCallAddress &&
561 buffer.pushed_count > 0) { 552 buffer.pushed_count > 0) {
562 ASSERT(deoptimization == NULL && continuation == NULL); 553 ASSERT(deoptimization == NULL && continuation == NULL);
563 Emit(kPopStack | MiscField::encode(buffer.pushed_count), NULL); 554 Emit(kPopStack | MiscField::encode(buffer.pushed_count), NULL);
564 } 555 }
565 } 556 }
566 557
567 } // namespace compiler 558 } // namespace compiler
568 } // namespace internal 559 } // namespace internal
569 } // namespace v8 560 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/arm64/instruction-selector-arm64.cc ('k') | src/compiler/instruction-selector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698