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

Side by Side Diff: src/compiler/x64/code-generator-x64.cc

Issue 733893008: [x64] Fix optimization for certain checked load/stores. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years 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
« no previous file with comments | « no previous file | src/compiler/x64/instruction-selector-x64.cc » ('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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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/code-generator.h" 5 #include "src/compiler/code-generator.h"
6 6
7 #include "src/compiler/code-generator-impl.h" 7 #include "src/compiler/code-generator-impl.h"
8 #include "src/compiler/gap-resolver.h" 8 #include "src/compiler/gap-resolver.h"
9 #include "src/compiler/node-matchers.h" 9 #include "src/compiler/node-matchers.h"
10 #include "src/compiler/node-properties-inl.h" 10 #include "src/compiler/node-properties-inl.h"
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 }; 131 };
132 132
133 133
134 namespace { 134 namespace {
135 135
136 bool HasImmediateInput(Instruction* instr, int index) { 136 bool HasImmediateInput(Instruction* instr, int index) {
137 return instr->InputAt(index)->IsImmediate(); 137 return instr->InputAt(index)->IsImmediate();
138 } 138 }
139 139
140 140
141 class OutOfLineLoadInteger FINAL : public OutOfLineCode { 141 class OutOfLineLoadZero FINAL : public OutOfLineCode {
142 public: 142 public:
143 OutOfLineLoadInteger(CodeGenerator* gen, Register result) 143 OutOfLineLoadZero(CodeGenerator* gen, Register result)
144 : OutOfLineCode(gen), result_(result) {} 144 : OutOfLineCode(gen), result_(result) {}
145 145
146 void Generate() FINAL { __ xorl(result_, result_); } 146 void Generate() FINAL { __ xorl(result_, result_); }
147 147
148 private: 148 private:
149 Register const result_; 149 Register const result_;
150 }; 150 };
151 151
152 152
153 class OutOfLineLoadFloat FINAL : public OutOfLineCode { 153 class OutOfLineLoadNaN FINAL : public OutOfLineCode {
154 public: 154 public:
155 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result) 155 OutOfLineLoadNaN(CodeGenerator* gen, XMMRegister result)
156 : OutOfLineCode(gen), result_(result) {} 156 : OutOfLineCode(gen), result_(result) {}
157 157
158 void Generate() FINAL { __ pcmpeqd(result_, result_); } 158 void Generate() FINAL { __ pcmpeqd(result_, result_); }
159 159
160 private: 160 private:
161 XMMRegister const result_; 161 XMMRegister const result_;
162 }; 162 };
163 163
164 164
165 class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { 165 class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 if (instr->InputAt(1)->IsDoubleRegister()) { \ 265 if (instr->InputAt(1)->IsDoubleRegister()) { \
266 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ 266 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
267 i.InputDoubleRegister(1)); \ 267 i.InputDoubleRegister(1)); \
268 } else { \ 268 } else { \
269 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ 269 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
270 i.InputOperand(1)); \ 270 i.InputOperand(1)); \
271 } \ 271 } \
272 } while (0) 272 } while (0)
273 273
274 274
275 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ 275 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \
276 do { \ 276 do { \
277 auto result = i.OutputDoubleRegister(); \ 277 auto result = i.OutputDoubleRegister(); \
278 auto offset = i.InputRegister(0); \ 278 auto buffer = i.InputRegister(0); \
279 if (instr->InputAt(1)->IsRegister()) { \ 279 auto index1 = i.InputRegister(1); \
280 __ cmpl(offset, i.InputRegister(1)); \ 280 auto index2 = i.InputInt32(2); \
281 } else { \ 281 OutOfLineCode* ool; \
282 __ cmpl(offset, i.InputImmediate(1)); \ 282 if (instr->InputAt(3)->IsRegister()) { \
283 } \ 283 auto length = i.InputRegister(3); \
284 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ 284 DCHECK_EQ(0, index2); \
285 __ j(above_equal, ool->entry()); \ 285 __ cmpl(index1, length); \
286 __ asm_instr(result, i.MemoryOperand(2)); \ 286 ool = new (zone()) OutOfLineLoadNaN(this, result); \
287 __ bind(ool->exit()); \ 287 } else { \
288 } while (false) 288 auto length = i.InputInt32(3); \
289 289 DCHECK_LE(index2, length); \
290 290 __ cmpl(index1, Immediate(length - index2)); \
291 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ 291 if (index2 == 0) { \
292 do { \ 292 ool = new (zone()) OutOfLineLoadNaN(this, result); \
293 auto result = i.OutputRegister(); \ 293 } else { \
294 auto offset = i.InputRegister(0); \ 294 class OutOfLineLoadFloat FINAL : public OutOfLineCode { \
295 if (instr->InputAt(1)->IsRegister()) { \ 295 public: \
296 __ cmpl(offset, i.InputRegister(1)); \ 296 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result, \
297 } else { \ 297 Register buffer, Register index1, int32_t index2, \
298 __ cmpl(offset, i.InputImmediate(1)); \ 298 int32_t length) \
299 } \ 299 : OutOfLineCode(gen), \
300 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ 300 result_(result), \
301 __ j(above_equal, ool->entry()); \ 301 buffer_(buffer), \
302 __ asm_instr(result, i.MemoryOperand(2)); \ 302 index1_(index1), \
303 __ bind(ool->exit()); \ 303 index2_(index2), \
304 } while (false) 304 length_(length) {} \
305 305 \
306 306 void Generate() FINAL { \
307 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ 307 DCHECK_NE(0, index2_); \
308 do { \ 308 __ leal(kScratchRegister, Operand(index1_, index2_)); \
309 auto offset = i.InputRegister(0); \ 309 __ pcmpeqd(result_, result_); \
310 if (instr->InputAt(1)->IsRegister()) { \ 310 __ cmpl(kScratchRegister, Immediate(length_)); \
311 __ cmpl(offset, i.InputRegister(1)); \ 311 __ j(above_equal, exit()); \
312 } else { \ 312 __ asm_instr(result_, \
313 __ cmpl(offset, i.InputImmediate(1)); \ 313 Operand(buffer_, kScratchRegister, times_1, 0)); \
314 } \ 314 } \
315 Label done; \ 315 \
316 __ j(above_equal, &done, Label::kNear); \ 316 private: \
317 __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \ 317 XMMRegister const result_; \
318 __ bind(&done); \ 318 Register const buffer_; \
319 } while (false) 319 Register const index1_; \
320 320 int32_t const index2_; \
321 321 int32_t const length_; \
322 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ 322 }; \
323 do { \ 323 ool = new (zone()) \
324 auto offset = i.InputRegister(0); \ 324 OutOfLineLoadFloat(this, result, buffer, index1, index2, length); \
325 if (instr->InputAt(1)->IsRegister()) { \ 325 } \
326 __ cmpl(offset, i.InputRegister(1)); \ 326 } \
327 } else { \ 327 __ j(above_equal, ool->entry()); \
328 __ cmpl(offset, i.InputImmediate(1)); \ 328 __ asm_instr(result, Operand(buffer, index1, times_1, index2)); \
329 } \ 329 __ bind(ool->exit()); \
330 Label done; \ 330 } while (false)
331 __ j(above_equal, &done, Label::kNear); \ 331
332 if (instr->InputAt(2)->IsRegister()) { \ 332
333 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ 333 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \
334 } else { \ 334 do { \
335 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ 335 auto result = i.OutputRegister(); \
336 } \ 336 auto buffer = i.InputRegister(0); \
337 __ bind(&done); \ 337 auto index1 = i.InputRegister(1); \
338 } while (false) 338 auto index2 = i.InputInt32(2); \
339 339 OutOfLineCode* ool; \
340 340 if (instr->InputAt(3)->IsRegister()) { \
341 auto length = i.InputRegister(3); \
342 DCHECK_EQ(0, index2); \
343 __ cmpl(index1, length); \
344 ool = new (zone()) OutOfLineLoadZero(this, result); \
345 } else { \
346 auto length = i.InputInt32(3); \
347 DCHECK_LE(index2, length); \
348 __ cmpl(index1, Immediate(length - index2)); \
349 if (index2 == 0) { \
350 ool = new (zone()) OutOfLineLoadZero(this, result); \
351 } else { \
352 class OutOfLineLoadInteger FINAL : public OutOfLineCode { \
353 public: \
354 OutOfLineLoadInteger(CodeGenerator* gen, Register result, \
355 Register buffer, Register index1, \
356 int32_t index2, int32_t length) \
357 : OutOfLineCode(gen), \
358 result_(result), \
359 buffer_(buffer), \
360 index1_(index1), \
361 index2_(index2), \
362 length_(length) {} \
363 \
364 void Generate() FINAL { \
365 DCHECK_NE(0, index2_); \
366 __ leal(kScratchRegister, Operand(index1_, index2_)); \
367 __ xorl(result_, result_); \
368 __ cmpl(kScratchRegister, Immediate(length_)); \
369 __ j(above_equal, exit()); \
370 __ asm_instr(result_, \
371 Operand(buffer_, kScratchRegister, times_1, 0)); \
372 } \
373 \
374 private: \
375 Register const result_; \
376 Register const buffer_; \
377 Register const index1_; \
378 int32_t const index2_; \
379 int32_t const length_; \
380 }; \
381 ool = new (zone()) OutOfLineLoadInteger(this, result, buffer, index1, \
382 index2, length); \
383 } \
384 } \
385 __ j(above_equal, ool->entry()); \
386 __ asm_instr(result, Operand(buffer, index1, times_1, index2)); \
387 __ bind(ool->exit()); \
388 } while (false)
389
390
391 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \
392 do { \
393 auto buffer = i.InputRegister(0); \
394 auto index1 = i.InputRegister(1); \
395 auto index2 = i.InputInt32(2); \
396 auto value = i.InputDoubleRegister(4); \
397 if (instr->InputAt(3)->IsRegister()) { \
398 auto length = i.InputRegister(3); \
399 DCHECK_EQ(0, index2); \
400 Label done; \
401 __ cmpl(index1, length); \
402 __ j(above_equal, &done, Label::kNear); \
403 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \
404 __ bind(&done); \
405 } else { \
406 auto length = i.InputInt32(3); \
407 DCHECK_LE(index2, length); \
408 __ cmpl(index1, Immediate(length - index2)); \
409 if (index2 == 0) { \
410 Label done; \
411 __ j(above_equal, &done, Label::kNear); \
412 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \
413 __ bind(&done); \
414 } else { \
415 class OutOfLineStoreFloat FINAL : public OutOfLineCode { \
416 public: \
417 OutOfLineStoreFloat(CodeGenerator* gen, Register buffer, \
418 Register index1, int32_t index2, int32_t length, \
419 XMMRegister value) \
420 : OutOfLineCode(gen), \
421 buffer_(buffer), \
422 index1_(index1), \
423 index2_(index2), \
424 length_(length), \
425 value_(value) {} \
426 \
427 void Generate() FINAL { \
428 DCHECK_NE(0, index2_); \
429 __ leal(kScratchRegister, Operand(index1_, index2_)); \
430 __ cmpl(kScratchRegister, Immediate(length_)); \
431 __ j(above_equal, exit()); \
432 __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0), \
433 value_); \
434 } \
435 \
436 private: \
437 Register const buffer_; \
438 Register const index1_; \
439 int32_t const index2_; \
440 int32_t const length_; \
441 XMMRegister const value_; \
442 }; \
443 auto ool = new (zone()) \
444 OutOfLineStoreFloat(this, buffer, index1, index2, length, value); \
445 __ j(above_equal, ool->entry()); \
446 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \
447 __ bind(ool->exit()); \
448 } \
449 } \
450 } while (false)
451
452
453 #define ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Value) \
454 do { \
455 auto buffer = i.InputRegister(0); \
456 auto index1 = i.InputRegister(1); \
457 auto index2 = i.InputInt32(2); \
458 if (instr->InputAt(3)->IsRegister()) { \
459 auto length = i.InputRegister(3); \
460 DCHECK_EQ(0, index2); \
461 Label done; \
462 __ cmpl(index1, length); \
463 __ j(above_equal, &done, Label::kNear); \
464 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \
465 __ bind(&done); \
466 } else { \
467 auto length = i.InputInt32(3); \
468 DCHECK_LE(index2, length); \
469 __ cmpl(index1, Immediate(length - index2)); \
470 if (index2 == 0) { \
471 Label done; \
472 __ j(above_equal, &done, Label::kNear); \
473 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \
474 __ bind(&done); \
475 } else { \
476 class OutOfLineStoreInteger FINAL : public OutOfLineCode { \
477 public: \
478 OutOfLineStoreInteger(CodeGenerator* gen, Register buffer, \
479 Register index1, int32_t index2, \
480 int32_t length, Value value) \
481 : OutOfLineCode(gen), \
482 buffer_(buffer), \
483 index1_(index1), \
484 index2_(index2), \
485 length_(length), \
486 value_(value) {} \
487 \
488 void Generate() FINAL { \
489 DCHECK_NE(0, index2_); \
490 __ leal(kScratchRegister, Operand(index1_, index2_)); \
491 __ cmpl(kScratchRegister, Immediate(length_)); \
492 __ j(above_equal, exit()); \
493 __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0), \
494 value_); \
495 } \
496 \
497 private: \
498 Register const buffer_; \
499 Register const index1_; \
500 int32_t const index2_; \
501 int32_t const length_; \
502 Value const value_; \
503 }; \
504 auto ool = new (zone()) OutOfLineStoreInteger(this, buffer, index1, \
505 index2, length, value); \
506 __ j(above_equal, ool->entry()); \
507 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \
508 __ bind(ool->exit()); \
509 } \
510 } \
511 } while (false)
512
513
514 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \
515 do { \
516 if (instr->InputAt(4)->IsRegister()) { \
517 Register value = i.InputRegister(4); \
518 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Register); \
519 } else { \
520 Immediate value = i.InputImmediate(4); \
521 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Immediate); \
522 } \
523 } while (false)
524
525
341 // Assembles an instruction after register allocation, producing machine code. 526 // Assembles an instruction after register allocation, producing machine code.
342 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { 527 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
343 X64OperandConverter i(this, instr); 528 X64OperandConverter i(this, instr);
344 529
345 switch (ArchOpcodeField::decode(instr->opcode())) { 530 switch (ArchOpcodeField::decode(instr->opcode())) {
346 case kArchCallCodeObject: { 531 case kArchCallCodeObject: {
347 EnsureSpaceForLazyDeopt(); 532 EnsureSpaceForLazyDeopt();
348 if (HasImmediateInput(instr, 0)) { 533 if (HasImmediateInput(instr, 0)) {
349 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 534 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
350 __ Call(code, RelocInfo::CODE_TARGET); 535 __ Call(code, RelocInfo::CODE_TARGET);
(...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 } 1437 }
1253 } 1438 }
1254 MarkLazyDeoptSite(); 1439 MarkLazyDeoptSite();
1255 } 1440 }
1256 1441
1257 #undef __ 1442 #undef __
1258 1443
1259 } // namespace internal 1444 } // namespace internal
1260 } // namespace compiler 1445 } // namespace compiler
1261 } // namespace v8 1446 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698