OLD | NEW |
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 case InstArithmetic::Urem: | 350 case InstArithmetic::Urem: |
351 TargetHelper = Ctx->getConstantExternSym(H_urem_i64); | 351 TargetHelper = Ctx->getConstantExternSym(H_urem_i64); |
352 break; | 352 break; |
353 case InstArithmetic::Srem: | 353 case InstArithmetic::Srem: |
354 TargetHelper = Ctx->getConstantExternSym(H_srem_i64); | 354 TargetHelper = Ctx->getConstantExternSym(H_srem_i64); |
355 break; | 355 break; |
356 } | 356 } |
357 assert(TargetHelper != nullptr); | 357 assert(TargetHelper != nullptr); |
358 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; | 358 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; |
359 constexpr SizeT MaxArgs = 2; | 359 constexpr SizeT MaxArgs = 2; |
360 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 360 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
361 NoTailCall, IsTargetHelperCall); | 361 NoTailCall, IsTargetHelperCall); |
362 Call->addArg(Instr->getSrc(0)); | 362 Call->addArg(Instr->getSrc(0)); |
363 Call->addArg(Instr->getSrc(1)); | 363 Call->addArg(Instr->getSrc(1)); |
364 Context.insert(Call); | |
365 Instr->setDeleted(); | 364 Instr->setDeleted(); |
366 return; | 365 return; |
367 } | 366 } |
368 case IceType_i32: | 367 case IceType_i32: |
369 case IceType_i16: | 368 case IceType_i16: |
370 case IceType_i8: { | 369 case IceType_i8: { |
371 const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm); | 370 const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm); |
372 InstCast::OpKind CastKind; | 371 InstCast::OpKind CastKind; |
373 Operand *TargetHelper; | 372 Operand *TargetHelper; |
374 switch (Op) { | 373 switch (Op) { |
(...skipping 26 matching lines...) Expand all Loading... |
401 // the following assert will have to be modified. | 400 // the following assert will have to be modified. |
402 assert(HasHWDiv); | 401 assert(HasHWDiv); |
403 return; | 402 return; |
404 } | 403 } |
405 Operand *Src0 = Instr->getSrc(0); | 404 Operand *Src0 = Instr->getSrc(0); |
406 Operand *Src1 = Instr->getSrc(1); | 405 Operand *Src1 = Instr->getSrc(1); |
407 if (DestTy != IceType_i32) { | 406 if (DestTy != IceType_i32) { |
408 // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0, | 407 // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0, |
409 // we just insert a InstCast right before the call to the helper. | 408 // we just insert a InstCast right before the call to the helper. |
410 Variable *Src0_32 = Func->makeVariable(IceType_i32); | 409 Variable *Src0_32 = Func->makeVariable(IceType_i32); |
411 Context.insert(InstCast::create(Func, CastKind, Src0_32, Src0)); | 410 Context.insert<InstCast>(CastKind, Src0_32, Src0); |
412 Src0 = Src0_32; | 411 Src0 = Src0_32; |
413 | 412 |
414 // For extending Src1, we will just insert an InstCast if Src1 is not a | 413 // For extending Src1, we will just insert an InstCast if Src1 is not a |
415 // Constant. If it is, then we extend it here, and not during program | 414 // Constant. If it is, then we extend it here, and not during program |
416 // runtime. This allows preambleDivRem to optimize-out the div-by-0 | 415 // runtime. This allows preambleDivRem to optimize-out the div-by-0 |
417 // check. | 416 // check. |
418 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { | 417 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { |
419 const int32_t ShAmt = (DestTy == IceType_i16) ? 16 : 24; | 418 const int32_t ShAmt = (DestTy == IceType_i16) ? 16 : 24; |
420 int32_t NewC = C->getValue(); | 419 int32_t NewC = C->getValue(); |
421 if (CastKind == InstCast::Zext) { | 420 if (CastKind == InstCast::Zext) { |
422 NewC &= ~(0x80000000l >> ShAmt); | 421 NewC &= ~(0x80000000l >> ShAmt); |
423 } else { | 422 } else { |
424 NewC = (NewC << ShAmt) >> ShAmt; | 423 NewC = (NewC << ShAmt) >> ShAmt; |
425 } | 424 } |
426 Src1 = Ctx->getConstantInt32(NewC); | 425 Src1 = Ctx->getConstantInt32(NewC); |
427 } else { | 426 } else { |
428 Variable *Src1_32 = Func->makeVariable(IceType_i32); | 427 Variable *Src1_32 = Func->makeVariable(IceType_i32); |
429 Context.insert(InstCast::create(Func, CastKind, Src1_32, Src1)); | 428 Context.insert<InstCast>(CastKind, Src1_32, Src1); |
430 Src1 = Src1_32; | 429 Src1 = Src1_32; |
431 } | 430 } |
432 } | 431 } |
433 assert(TargetHelper != nullptr); | 432 assert(TargetHelper != nullptr); |
434 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; | 433 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; |
435 constexpr SizeT MaxArgs = 2; | 434 constexpr SizeT MaxArgs = 2; |
436 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 435 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
437 NoTailCall, IsTargetHelperCall); | 436 NoTailCall, IsTargetHelperCall); |
438 assert(Src0->getType() == IceType_i32); | 437 assert(Src0->getType() == IceType_i32); |
439 Call->addArg(Src0); | 438 Call->addArg(Src0); |
440 assert(Src1->getType() == IceType_i32); | 439 assert(Src1->getType() == IceType_i32); |
441 Call->addArg(Src1); | 440 Call->addArg(Src1); |
442 Context.insert(Call); | |
443 Instr->setDeleted(); | 441 Instr->setDeleted(); |
444 return; | 442 return; |
445 } | 443 } |
446 case IceType_f64: | 444 case IceType_f64: |
447 case IceType_f32: { | 445 case IceType_f32: { |
448 if (Op != InstArithmetic::Frem) { | 446 if (Op != InstArithmetic::Frem) { |
449 return; | 447 return; |
450 } | 448 } |
451 constexpr SizeT MaxArgs = 2; | 449 constexpr SizeT MaxArgs = 2; |
452 Operand *TargetHelper = Ctx->getConstantExternSym( | 450 Operand *TargetHelper = Ctx->getConstantExternSym( |
453 DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64); | 451 DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64); |
454 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 452 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
455 NoTailCall, IsTargetHelperCall); | 453 NoTailCall, IsTargetHelperCall); |
456 Call->addArg(Instr->getSrc(0)); | 454 Call->addArg(Instr->getSrc(0)); |
457 Call->addArg(Instr->getSrc(1)); | 455 Call->addArg(Instr->getSrc(1)); |
458 Context.insert(Call); | |
459 Instr->setDeleted(); | 456 Instr->setDeleted(); |
460 return; | 457 return; |
461 } | 458 } |
462 } | 459 } |
463 llvm::report_fatal_error("Control flow should never have reached here."); | 460 llvm::report_fatal_error("Control flow should never have reached here."); |
464 } | 461 } |
465 case Inst::Cast: { | 462 case Inst::Cast: { |
466 Variable *Dest = Instr->getDest(); | 463 Variable *Dest = Instr->getDest(); |
467 Operand *Src0 = Instr->getSrc(0); | 464 Operand *Src0 = Instr->getSrc(0); |
468 const Type DestTy = Dest->getType(); | 465 const Type DestTy = Dest->getType(); |
469 const InstCast::OpKind CastKind = | 466 const InstCast::OpKind CastKind = |
470 llvm::cast<InstCast>(Instr)->getCastKind(); | 467 llvm::cast<InstCast>(Instr)->getCastKind(); |
471 switch (CastKind) { | 468 switch (CastKind) { |
472 default: | 469 default: |
473 return; | 470 return; |
474 case InstCast::Fptosi: | 471 case InstCast::Fptosi: |
475 case InstCast::Fptoui: { | 472 case InstCast::Fptoui: { |
476 if (DestTy != IceType_i64) { | 473 if (DestTy != IceType_i64) { |
477 return; | 474 return; |
478 } | 475 } |
479 const bool DestIsSigned = CastKind == InstCast::Fptosi; | 476 const bool DestIsSigned = CastKind == InstCast::Fptosi; |
480 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); | 477 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); |
481 Operand *TargetHelper = Ctx->getConstantExternSym( | 478 Operand *TargetHelper = Ctx->getConstantExternSym( |
482 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64) | 479 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64) |
483 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64)); | 480 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64)); |
484 static constexpr SizeT MaxArgs = 1; | 481 static constexpr SizeT MaxArgs = 1; |
485 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 482 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
486 NoTailCall, IsTargetHelperCall); | 483 NoTailCall, IsTargetHelperCall); |
487 Call->addArg(Src0); | 484 Call->addArg(Src0); |
488 Context.insert(Call); | |
489 Instr->setDeleted(); | 485 Instr->setDeleted(); |
490 return; | 486 return; |
491 } | 487 } |
492 case InstCast::Sitofp: | 488 case InstCast::Sitofp: |
493 case InstCast::Uitofp: { | 489 case InstCast::Uitofp: { |
494 if (Src0->getType() != IceType_i64) { | 490 if (Src0->getType() != IceType_i64) { |
495 return; | 491 return; |
496 } | 492 } |
497 const bool SourceIsSigned = CastKind == InstCast::Sitofp; | 493 const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
498 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); | 494 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); |
499 Operand *TargetHelper = Ctx->getConstantExternSym( | 495 Operand *TargetHelper = Ctx->getConstantExternSym( |
500 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32) | 496 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32) |
501 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64)); | 497 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64)); |
502 static constexpr SizeT MaxArgs = 1; | 498 static constexpr SizeT MaxArgs = 1; |
503 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 499 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
504 NoTailCall, IsTargetHelperCall); | 500 NoTailCall, IsTargetHelperCall); |
505 Call->addArg(Src0); | 501 Call->addArg(Src0); |
506 Context.insert(Call); | |
507 Instr->setDeleted(); | 502 Instr->setDeleted(); |
508 return; | 503 return; |
509 } | 504 } |
510 } | 505 } |
511 llvm::report_fatal_error("Control flow should never have reached here."); | 506 llvm::report_fatal_error("Control flow should never have reached here."); |
512 } | 507 } |
513 case Inst::IntrinsicCall: { | 508 case Inst::IntrinsicCall: { |
514 Variable *Dest = Instr->getDest(); | 509 Variable *Dest = Instr->getDest(); |
515 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); | 510 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); |
516 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; | 511 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; |
517 switch (ID) { | 512 switch (ID) { |
518 default: | 513 default: |
519 return; | 514 return; |
520 case Intrinsics::Ctpop: { | 515 case Intrinsics::Ctpop: { |
521 Operand *Src0 = IntrinsicCall->getArg(0); | 516 Operand *Src0 = IntrinsicCall->getArg(0); |
522 Operand *TargetHelper = Ctx->getConstantExternSym( | 517 Operand *TargetHelper = Ctx->getConstantExternSym( |
523 isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32 | 518 isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32 |
524 : H_call_ctpop_i64); | 519 : H_call_ctpop_i64); |
525 static constexpr SizeT MaxArgs = 1; | 520 static constexpr SizeT MaxArgs = 1; |
526 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 521 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
527 NoTailCall, IsTargetHelperCall); | 522 NoTailCall, IsTargetHelperCall); |
528 Call->addArg(Src0); | 523 Call->addArg(Src0); |
529 Context.insert(Call); | |
530 Instr->setDeleted(); | 524 Instr->setDeleted(); |
531 if (Src0->getType() == IceType_i64) { | 525 if (Src0->getType() == IceType_i64) { |
532 ARM32HelpersPostamble[TargetHelper] = &TargetARM32::postambleCtpop64; | 526 ARM32HelpersPostamble[TargetHelper] = &TargetARM32::postambleCtpop64; |
533 } | 527 } |
534 return; | 528 return; |
535 } | 529 } |
536 case Intrinsics::Longjmp: { | 530 case Intrinsics::Longjmp: { |
537 static constexpr SizeT MaxArgs = 2; | 531 static constexpr SizeT MaxArgs = 2; |
538 static constexpr Variable *NoDest = nullptr; | 532 static constexpr Variable *NoDest = nullptr; |
539 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_longjmp); | 533 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_longjmp); |
540 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 534 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
541 NoTailCall, IsTargetHelperCall); | 535 NoTailCall, IsTargetHelperCall); |
542 Call->addArg(IntrinsicCall->getArg(0)); | 536 Call->addArg(IntrinsicCall->getArg(0)); |
543 Call->addArg(IntrinsicCall->getArg(1)); | 537 Call->addArg(IntrinsicCall->getArg(1)); |
544 Context.insert(Call); | |
545 Instr->setDeleted(); | 538 Instr->setDeleted(); |
546 return; | 539 return; |
547 } | 540 } |
548 case Intrinsics::Memcpy: { | 541 case Intrinsics::Memcpy: { |
549 // In the future, we could potentially emit an inline memcpy/memset, etc. | 542 // In the future, we could potentially emit an inline memcpy/memset, etc. |
550 // for intrinsic calls w/ a known length. | 543 // for intrinsic calls w/ a known length. |
551 static constexpr SizeT MaxArgs = 3; | 544 static constexpr SizeT MaxArgs = 3; |
552 static constexpr Variable *NoDest = nullptr; | 545 static constexpr Variable *NoDest = nullptr; |
553 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memcpy); | 546 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memcpy); |
554 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 547 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
555 NoTailCall, IsTargetHelperCall); | 548 NoTailCall, IsTargetHelperCall); |
556 Call->addArg(IntrinsicCall->getArg(0)); | 549 Call->addArg(IntrinsicCall->getArg(0)); |
557 Call->addArg(IntrinsicCall->getArg(1)); | 550 Call->addArg(IntrinsicCall->getArg(1)); |
558 Call->addArg(IntrinsicCall->getArg(2)); | 551 Call->addArg(IntrinsicCall->getArg(2)); |
559 Context.insert(Call); | |
560 Instr->setDeleted(); | 552 Instr->setDeleted(); |
561 return; | 553 return; |
562 } | 554 } |
563 case Intrinsics::Memmove: { | 555 case Intrinsics::Memmove: { |
564 static constexpr SizeT MaxArgs = 3; | 556 static constexpr SizeT MaxArgs = 3; |
565 static constexpr Variable *NoDest = nullptr; | 557 static constexpr Variable *NoDest = nullptr; |
566 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memmove); | 558 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memmove); |
567 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 559 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
568 NoTailCall, IsTargetHelperCall); | 560 NoTailCall, IsTargetHelperCall); |
569 Call->addArg(IntrinsicCall->getArg(0)); | 561 Call->addArg(IntrinsicCall->getArg(0)); |
570 Call->addArg(IntrinsicCall->getArg(1)); | 562 Call->addArg(IntrinsicCall->getArg(1)); |
571 Call->addArg(IntrinsicCall->getArg(2)); | 563 Call->addArg(IntrinsicCall->getArg(2)); |
572 Context.insert(Call); | |
573 Instr->setDeleted(); | 564 Instr->setDeleted(); |
574 return; | 565 return; |
575 } | 566 } |
576 case Intrinsics::Memset: { | 567 case Intrinsics::Memset: { |
577 // The value operand needs to be extended to a stack slot size because the | 568 // The value operand needs to be extended to a stack slot size because the |
578 // PNaCl ABI requires arguments to be at least 32 bits wide. | 569 // PNaCl ABI requires arguments to be at least 32 bits wide. |
579 Operand *ValOp = IntrinsicCall->getArg(1); | 570 Operand *ValOp = IntrinsicCall->getArg(1); |
580 assert(ValOp->getType() == IceType_i8); | 571 assert(ValOp->getType() == IceType_i8); |
581 Variable *ValExt = Func->makeVariable(stackSlotType()); | 572 Variable *ValExt = Func->makeVariable(stackSlotType()); |
582 Context.insert(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); | 573 Context.insert<InstCast>(InstCast::Zext, ValExt, ValOp); |
583 | 574 |
584 // Technically, ARM has its own __aeabi_memset, but we can use plain | 575 // Technically, ARM has its own __aeabi_memset, but we can use plain |
585 // memset too. The value and size argument need to be flipped if we ever | 576 // memset too. The value and size argument need to be flipped if we ever |
586 // decide to use __aeabi_memset. | 577 // decide to use __aeabi_memset. |
587 static constexpr SizeT MaxArgs = 3; | 578 static constexpr SizeT MaxArgs = 3; |
588 static constexpr Variable *NoDest = nullptr; | 579 static constexpr Variable *NoDest = nullptr; |
589 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset); | 580 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset); |
590 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 581 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
591 NoTailCall, IsTargetHelperCall); | 582 NoTailCall, IsTargetHelperCall); |
592 Call->addArg(IntrinsicCall->getArg(0)); | 583 Call->addArg(IntrinsicCall->getArg(0)); |
593 Call->addArg(ValExt); | 584 Call->addArg(ValExt); |
594 Call->addArg(IntrinsicCall->getArg(2)); | 585 Call->addArg(IntrinsicCall->getArg(2)); |
595 Context.insert(Call); | |
596 Instr->setDeleted(); | 586 Instr->setDeleted(); |
597 return; | 587 return; |
598 } | 588 } |
599 case Intrinsics::NaClReadTP: { | 589 case Intrinsics::NaClReadTP: { |
600 if (NeedSandboxing) { | 590 if (NeedSandboxing) { |
601 return; | 591 return; |
602 } | 592 } |
603 static constexpr SizeT MaxArgs = 0; | 593 static constexpr SizeT MaxArgs = 0; |
604 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp); | 594 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp); |
605 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 595 Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall, |
606 NoTailCall, IsTargetHelperCall); | 596 IsTargetHelperCall); |
607 Context.insert(Call); | |
608 Instr->setDeleted(); | 597 Instr->setDeleted(); |
609 return; | 598 return; |
610 } | 599 } |
611 case Intrinsics::Setjmp: { | 600 case Intrinsics::Setjmp: { |
612 static constexpr SizeT MaxArgs = 1; | 601 static constexpr SizeT MaxArgs = 1; |
613 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_setjmp); | 602 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_setjmp); |
614 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 603 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
615 NoTailCall, IsTargetHelperCall); | 604 NoTailCall, IsTargetHelperCall); |
616 Call->addArg(IntrinsicCall->getArg(0)); | 605 Call->addArg(IntrinsicCall->getArg(0)); |
617 Context.insert(Call); | |
618 Instr->setDeleted(); | 606 Instr->setDeleted(); |
619 return; | 607 return; |
620 } | 608 } |
621 } | 609 } |
622 llvm::report_fatal_error("Control flow should never have reached here."); | 610 llvm::report_fatal_error("Control flow should never have reached here."); |
623 } | 611 } |
624 } | 612 } |
625 } | 613 } |
626 | 614 |
627 void TargetARM32::findMaxStackOutArgsSize() { | 615 void TargetARM32::findMaxStackOutArgsSize() { |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 default: { RegisterArg->setRegNum(RegNum); } break; | 1011 default: { RegisterArg->setRegNum(RegNum); } break; |
1024 case IceType_i64: { | 1012 case IceType_i64: { |
1025 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); | 1013 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); |
1026 RegisterArg64->initHiLo(Func); | 1014 RegisterArg64->initHiLo(Func); |
1027 RegisterArg64->getLo()->setRegNum( | 1015 RegisterArg64->getLo()->setRegNum( |
1028 RegARM32::getI64PairFirstGPRNum(RegNum)); | 1016 RegARM32::getI64PairFirstGPRNum(RegNum)); |
1029 RegisterArg64->getHi()->setRegNum( | 1017 RegisterArg64->getHi()->setRegNum( |
1030 RegARM32::getI64PairSecondGPRNum(RegNum)); | 1018 RegARM32::getI64PairSecondGPRNum(RegNum)); |
1031 } break; | 1019 } break; |
1032 } | 1020 } |
1033 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 1021 Context.insert<InstAssign>(Arg, RegisterArg); |
1034 } | 1022 } |
1035 } | 1023 } |
1036 | 1024 |
1037 // Helper function for addProlog(). | 1025 // Helper function for addProlog(). |
1038 // | 1026 // |
1039 // This assumes Arg is an argument passed on the stack. This sets the frame | 1027 // This assumes Arg is an argument passed on the stack. This sets the frame |
1040 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 1028 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an |
1041 // I64 arg that has been split into Lo and Hi components, it calls itself | 1029 // I64 arg that has been split into Lo and Hi components, it calls itself |
1042 // recursively on the components, taking care to handle Lo first because of the | 1030 // recursively on the components, taking care to handle Lo first because of the |
1043 // little-endian architecture. Lastly, this function generates an instruction | 1031 // little-endian architecture. Lastly, this function generates an instruction |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 _push(PreservedSRegs); | 1212 _push(PreservedSRegs); |
1225 if (!PreservedGPRs.empty()) | 1213 if (!PreservedGPRs.empty()) |
1226 _push(PreservedGPRs); | 1214 _push(PreservedGPRs); |
1227 | 1215 |
1228 // Generate "mov FP, SP" if needed. | 1216 // Generate "mov FP, SP" if needed. |
1229 if (UsesFramePointer) { | 1217 if (UsesFramePointer) { |
1230 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); | 1218 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); |
1231 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1219 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
1232 _mov(FP, SP); | 1220 _mov(FP, SP); |
1233 // Keep FP live for late-stage liveness analysis (e.g. asm-verbose mode). | 1221 // Keep FP live for late-stage liveness analysis (e.g. asm-verbose mode). |
1234 Context.insert(InstFakeUse::create(Func, FP)); | 1222 Context.insert<InstFakeUse>(FP); |
1235 } | 1223 } |
1236 | 1224 |
1237 // Align the variables area. SpillAreaPaddingBytes is the size of the region | 1225 // Align the variables area. SpillAreaPaddingBytes is the size of the region |
1238 // after the preserved registers and before the spill areas. | 1226 // after the preserved registers and before the spill areas. |
1239 // LocalsSlotsPaddingBytes is the amount of padding between the globals and | 1227 // LocalsSlotsPaddingBytes is the amount of padding between the globals and |
1240 // locals area if they are separate. | 1228 // locals area if they are separate. |
1241 assert(SpillAreaAlignmentBytes <= ARM32_STACK_ALIGNMENT_BYTES); | 1229 assert(SpillAreaAlignmentBytes <= ARM32_STACK_ALIGNMENT_BYTES); |
1242 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); | 1230 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); |
1243 uint32_t SpillAreaPaddingBytes = 0; | 1231 uint32_t SpillAreaPaddingBytes = 0; |
1244 uint32_t LocalsSlotsPaddingBytes = 0; | 1232 uint32_t LocalsSlotsPaddingBytes = 0; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1353 --InsertPoint; | 1341 --InsertPoint; |
1354 Context.init(Node); | 1342 Context.init(Node); |
1355 Context.setInsertPoint(InsertPoint); | 1343 Context.setInsertPoint(InsertPoint); |
1356 | 1344 |
1357 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1345 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
1358 if (UsesFramePointer) { | 1346 if (UsesFramePointer) { |
1359 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); | 1347 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); |
1360 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | 1348 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
1361 // use of SP before the assignment of SP=FP keeps previous SP adjustments | 1349 // use of SP before the assignment of SP=FP keeps previous SP adjustments |
1362 // from being dead-code eliminated. | 1350 // from being dead-code eliminated. |
1363 Context.insert(InstFakeUse::create(Func, SP)); | 1351 Context.insert<InstFakeUse>(SP); |
1364 Sandboxer(this).reset_sp(FP); | 1352 Sandboxer(this).reset_sp(FP); |
1365 } else { | 1353 } else { |
1366 // add SP, SpillAreaSizeBytes | 1354 // add SP, SpillAreaSizeBytes |
1367 if (SpillAreaSizeBytes) { | 1355 if (SpillAreaSizeBytes) { |
1368 // Use the scratch register if needed to legalize the immediate. | 1356 // Use the scratch register if needed to legalize the immediate. |
1369 Operand *AddAmount = | 1357 Operand *AddAmount = |
1370 legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), | 1358 legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), |
1371 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 1359 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
1372 Sandboxer(this).add_sp(AddAmount); | 1360 Sandboxer(this).add_sp(AddAmount); |
1373 } | 1361 } |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 if (!Dest->hasReg()) { | 1505 if (!Dest->hasReg()) { |
1518 auto *SrcR = llvm::cast<Variable>(Src); | 1506 auto *SrcR = llvm::cast<Variable>(Src); |
1519 assert(SrcR->hasReg()); | 1507 assert(SrcR->hasReg()); |
1520 assert(!SrcR->isRematerializable()); | 1508 assert(!SrcR->isRematerializable()); |
1521 const int32_t Offset = Dest->getStackOffset(); | 1509 const int32_t Offset = Dest->getStackOffset(); |
1522 // This is a _mov(Mem(), Variable), i.e., a store. | 1510 // This is a _mov(Mem(), Variable), i.e., a store. |
1523 TargetARM32::Sandboxer(Target) | 1511 TargetARM32::Sandboxer(Target) |
1524 .str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset), | 1512 .str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset), |
1525 MovInstr->getPredicate()); | 1513 MovInstr->getPredicate()); |
1526 // _str() does not have a Dest, so we add a fake-def(Dest). | 1514 // _str() does not have a Dest, so we add a fake-def(Dest). |
1527 Target->Context.insert(InstFakeDef::create(Target->Func, Dest)); | 1515 Target->Context.insert<InstFakeDef>(Dest); |
1528 Legalized = true; | 1516 Legalized = true; |
1529 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1517 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
1530 if (Var->isRematerializable()) { | 1518 if (Var->isRematerializable()) { |
1531 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1519 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
1532 | 1520 |
1533 // ExtraOffset is only needed for frame-pointer based frames as we have | 1521 // ExtraOffset is only needed for frame-pointer based frames as we have |
1534 // to account for spill storage. | 1522 // to account for spill storage. |
1535 const int32_t ExtraOffset = | 1523 const int32_t ExtraOffset = |
1536 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) | 1524 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) |
1537 ? Target->getFrameFixedAllocaOffset() | 1525 ? Target->getFrameFixedAllocaOffset() |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1892 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { | 1880 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { |
1893 const uint32_t Value = | 1881 const uint32_t Value = |
1894 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); | 1882 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); |
1895 // Constant size alloca. | 1883 // Constant size alloca. |
1896 if (!UseFramePointer) { | 1884 if (!UseFramePointer) { |
1897 // If we don't need a Frame Pointer, this alloca has a known offset to the | 1885 // If we don't need a Frame Pointer, this alloca has a known offset to the |
1898 // stack pointer. We don't need adjust the stack pointer, nor assign any | 1886 // stack pointer. We don't need adjust the stack pointer, nor assign any |
1899 // value to Dest, as Dest is rematerializable. | 1887 // value to Dest, as Dest is rematerializable. |
1900 assert(Dest->isRematerializable()); | 1888 assert(Dest->isRematerializable()); |
1901 FixedAllocaSizeBytes += Value; | 1889 FixedAllocaSizeBytes += Value; |
1902 Context.insert(InstFakeDef::create(Func, Dest)); | 1890 Context.insert<InstFakeDef>(Dest); |
1903 return; | 1891 return; |
1904 } | 1892 } |
1905 | 1893 |
1906 // If a frame pointer is required, then we need to store the alloca'd result | 1894 // If a frame pointer is required, then we need to store the alloca'd result |
1907 // in Dest. | 1895 // in Dest. |
1908 Operand *SubAmountRF = | 1896 Operand *SubAmountRF = |
1909 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); | 1897 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); |
1910 Sandboxer(this).sub_sp(SubAmountRF); | 1898 Sandboxer(this).sub_sp(SubAmountRF); |
1911 } else { | 1899 } else { |
1912 // Non-constant sizes need to be adjusted to the next highest multiple of | 1900 // Non-constant sizes need to be adjusted to the next highest multiple of |
(...skipping 24 matching lines...) Expand all Loading... |
1937 return; | 1925 return; |
1938 Variable *SrcLoReg = legalizeToReg(SrcLo); | 1926 Variable *SrcLoReg = legalizeToReg(SrcLo); |
1939 switch (Ty) { | 1927 switch (Ty) { |
1940 default: | 1928 default: |
1941 llvm::report_fatal_error("Unexpected type"); | 1929 llvm::report_fatal_error("Unexpected type"); |
1942 case IceType_i8: | 1930 case IceType_i8: |
1943 case IceType_i16: { | 1931 case IceType_i16: { |
1944 Operand *ShAmtImm = shAmtImm(32 - getScalarIntBitWidth(Ty)); | 1932 Operand *ShAmtImm = shAmtImm(32 - getScalarIntBitWidth(Ty)); |
1945 Variable *T = makeReg(IceType_i32); | 1933 Variable *T = makeReg(IceType_i32); |
1946 _lsls(T, SrcLoReg, ShAmtImm); | 1934 _lsls(T, SrcLoReg, ShAmtImm); |
1947 Context.insert(InstFakeUse::create(Func, T)); | 1935 Context.insert<InstFakeUse>(T); |
1948 } break; | 1936 } break; |
1949 case IceType_i32: { | 1937 case IceType_i32: { |
1950 _tst(SrcLoReg, SrcLoReg); | 1938 _tst(SrcLoReg, SrcLoReg); |
1951 break; | 1939 break; |
1952 } | 1940 } |
1953 case IceType_i64: { | 1941 case IceType_i64: { |
1954 Variable *T = makeReg(IceType_i32); | 1942 Variable *T = makeReg(IceType_i32); |
1955 _orrs(T, SrcLoReg, legalize(SrcHi, Legal_Reg | Legal_Flex)); | 1943 _orrs(T, SrcLoReg, legalize(SrcHi, Legal_Reg | Legal_Flex)); |
1956 // T isn't going to be used, but we need the side-effect of setting flags | 1944 // T isn't going to be used, but we need the side-effect of setting flags |
1957 // from this operation. | 1945 // from this operation. |
1958 Context.insert(InstFakeUse::create(Func, T)); | 1946 Context.insert<InstFakeUse>(T); |
1959 } | 1947 } |
1960 } | 1948 } |
1961 auto *Label = InstARM32Label::create(Func, this); | 1949 auto *Label = InstARM32Label::create(Func, this); |
1962 _br(Label, CondARM32::NE); | 1950 _br(Label, CondARM32::NE); |
1963 _trap(); | 1951 _trap(); |
1964 Context.insert(Label); | 1952 Context.insert(Label); |
1965 } | 1953 } |
1966 | 1954 |
1967 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, | 1955 void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, |
1968 Operand *Src1, ExtInstr ExtFunc, | 1956 Operand *Src1, ExtInstr ExtFunc, |
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2704 | 2692 |
2705 return Src == 0; | 2693 return Src == 0; |
2706 } | 2694 } |
2707 } // end of namespace StrengthReduction | 2695 } // end of namespace StrengthReduction |
2708 } // end of anonymous namespace | 2696 } // end of anonymous namespace |
2709 | 2697 |
2710 void TargetARM32::lowerArithmetic(const InstArithmetic *Instr) { | 2698 void TargetARM32::lowerArithmetic(const InstArithmetic *Instr) { |
2711 Variable *Dest = Instr->getDest(); | 2699 Variable *Dest = Instr->getDest(); |
2712 | 2700 |
2713 if (Dest->isRematerializable()) { | 2701 if (Dest->isRematerializable()) { |
2714 Context.insert(InstFakeDef::create(Func, Dest)); | 2702 Context.insert<InstFakeDef>(Dest); |
2715 return; | 2703 return; |
2716 } | 2704 } |
2717 | 2705 |
2718 Type DestTy = Dest->getType(); | 2706 Type DestTy = Dest->getType(); |
2719 if (DestTy == IceType_i1) { | 2707 if (DestTy == IceType_i1) { |
2720 lowerInt1Arithmetic(Instr); | 2708 lowerInt1Arithmetic(Instr); |
2721 return; | 2709 return; |
2722 } | 2710 } |
2723 | 2711 |
2724 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); | 2712 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); |
2725 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); | 2713 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); |
2726 if (DestTy == IceType_i64) { | 2714 if (DestTy == IceType_i64) { |
2727 lowerInt64Arithmetic(Instr->getOp(), Instr->getDest(), Src0, Src1); | 2715 lowerInt64Arithmetic(Instr->getOp(), Instr->getDest(), Src0, Src1); |
2728 return; | 2716 return; |
2729 } | 2717 } |
2730 | 2718 |
2731 if (isVectorType(DestTy)) { | 2719 if (isVectorType(DestTy)) { |
2732 // Add a fake def to keep liveness consistent in the meantime. | 2720 // Add a fake def to keep liveness consistent in the meantime. |
2733 Variable *T = makeReg(DestTy); | 2721 Variable *T = makeReg(DestTy); |
2734 Context.insert(InstFakeDef::create(Func, T)); | 2722 Context.insert<InstFakeDef>(T); |
2735 _mov(Dest, T); | 2723 _mov(Dest, T); |
2736 UnimplementedError(Func->getContext()->getFlags()); | 2724 UnimplementedError(Func->getContext()->getFlags()); |
2737 return; | 2725 return; |
2738 } | 2726 } |
2739 | 2727 |
2740 // DestTy is a non-i64 scalar. | 2728 // DestTy is a non-i64 scalar. |
2741 Variable *T = makeReg(DestTy); | 2729 Variable *T = makeReg(DestTy); |
2742 | 2730 |
2743 // * Handle div/rem separately. They require a non-legalized Src1 to inspect | 2731 // * Handle div/rem separately. They require a non-legalized Src1 to inspect |
2744 // whether or not Src1 is a non-zero constant. Once legalized it is more | 2732 // whether or not Src1 is a non-zero constant. Once legalized it is more |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3056 llvm::report_fatal_error( | 3044 llvm::report_fatal_error( |
3057 "Floating point arith should have been handled earlier."); | 3045 "Floating point arith should have been handled earlier."); |
3058 return; | 3046 return; |
3059 } | 3047 } |
3060 } | 3048 } |
3061 | 3049 |
3062 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 3050 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
3063 Variable *Dest = Inst->getDest(); | 3051 Variable *Dest = Inst->getDest(); |
3064 | 3052 |
3065 if (Dest->isRematerializable()) { | 3053 if (Dest->isRematerializable()) { |
3066 Context.insert(InstFakeDef::create(Func, Dest)); | 3054 Context.insert<InstFakeDef>(Dest); |
3067 return; | 3055 return; |
3068 } | 3056 } |
3069 | 3057 |
3070 Operand *Src0 = Inst->getSrc(0); | 3058 Operand *Src0 = Inst->getSrc(0); |
3071 assert(Dest->getType() == Src0->getType()); | 3059 assert(Dest->getType() == Src0->getType()); |
3072 if (Dest->getType() == IceType_i64) { | 3060 if (Dest->getType() == IceType_i64) { |
3073 Src0 = legalizeUndef(Src0); | 3061 Src0 = legalizeUndef(Src0); |
3074 | 3062 |
3075 Variable *T_Lo = makeReg(IceType_i32); | 3063 Variable *T_Lo = makeReg(IceType_i32); |
3076 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 3064 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3360 // Allow ConstantRelocatable to be left alone as a direct call, but force | 3348 // Allow ConstantRelocatable to be left alone as a direct call, but force |
3361 // other constants like ConstantInteger32 to be in a register and make it an | 3349 // other constants like ConstantInteger32 to be in a register and make it an |
3362 // indirect call. | 3350 // indirect call. |
3363 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 3351 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
3364 CallTarget = legalize(CallTarget, Legal_Reg); | 3352 CallTarget = legalize(CallTarget, Legal_Reg); |
3365 } | 3353 } |
3366 | 3354 |
3367 // Copy arguments to be passed in registers to the appropriate registers. | 3355 // Copy arguments to be passed in registers to the appropriate registers. |
3368 for (auto &FPArg : FPArgs) { | 3356 for (auto &FPArg : FPArgs) { |
3369 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); | 3357 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); |
3370 Context.insert(InstFakeUse::create(Func, Reg)); | 3358 Context.insert<InstFakeUse>(Reg); |
3371 } | 3359 } |
3372 for (auto &GPRArg : GPRArgs) { | 3360 for (auto &GPRArg : GPRArgs) { |
3373 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); | 3361 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); |
3374 // Generate a FakeUse of register arguments so that they do not get dead | 3362 // Generate a FakeUse of register arguments so that they do not get dead |
3375 // code eliminated as a result of the FakeKill of scratch registers after | 3363 // code eliminated as a result of the FakeKill of scratch registers after |
3376 // the call. | 3364 // the call. |
3377 Context.insert(InstFakeUse::create(Func, Reg)); | 3365 Context.insert<InstFakeUse>(Reg); |
3378 } | 3366 } |
3379 | 3367 |
3380 InstARM32Call *NewCall = | 3368 InstARM32Call *NewCall = |
3381 Sandboxer(this, InstBundleLock::Opt_AlignToEnd).bl(ReturnReg, CallTarget); | 3369 Sandboxer(this, InstBundleLock::Opt_AlignToEnd).bl(ReturnReg, CallTarget); |
3382 | 3370 |
3383 if (ReturnRegHi) | 3371 if (ReturnRegHi) |
3384 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 3372 Context.insert<InstFakeDef>(ReturnRegHi); |
3385 | 3373 |
3386 // Insert a register-kill pseudo instruction. | 3374 // Insert a register-kill pseudo instruction. |
3387 Context.insert(InstFakeKill::create(Func, NewCall)); | 3375 Context.insert<InstFakeKill>(NewCall); |
3388 | 3376 |
3389 // Generate a FakeUse to keep the call live if necessary. | 3377 // Generate a FakeUse to keep the call live if necessary. |
3390 if (Instr->hasSideEffects() && ReturnReg) { | 3378 if (Instr->hasSideEffects() && ReturnReg) { |
3391 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 3379 Context.insert<InstFakeUse>(ReturnReg); |
3392 Context.insert(FakeUse); | |
3393 } | 3380 } |
3394 | 3381 |
3395 if (Dest != nullptr) { | 3382 if (Dest != nullptr) { |
3396 // Assign the result of the call to Dest. | 3383 // Assign the result of the call to Dest. |
3397 if (ReturnReg != nullptr) { | 3384 if (ReturnReg != nullptr) { |
3398 if (ReturnRegHi) { | 3385 if (ReturnRegHi) { |
3399 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 3386 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
3400 Variable *DestLo = Dest64On32->getLo(); | 3387 Variable *DestLo = Dest64On32->getLo(); |
3401 Variable *DestHi = Dest64On32->getHi(); | 3388 Variable *DestHi = Dest64On32->getHi(); |
3402 _mov(DestLo, ReturnReg); | 3389 _mov(DestLo, ReturnReg); |
(...skipping 30 matching lines...) Expand all Loading... |
3433 InstCast::OpKind CastKind = Inst->getCastKind(); | 3420 InstCast::OpKind CastKind = Inst->getCastKind(); |
3434 Variable *Dest = Inst->getDest(); | 3421 Variable *Dest = Inst->getDest(); |
3435 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 3422 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
3436 switch (CastKind) { | 3423 switch (CastKind) { |
3437 default: | 3424 default: |
3438 Func->setError("Cast type not supported"); | 3425 Func->setError("Cast type not supported"); |
3439 return; | 3426 return; |
3440 case InstCast::Sext: { | 3427 case InstCast::Sext: { |
3441 if (isVectorType(Dest->getType())) { | 3428 if (isVectorType(Dest->getType())) { |
3442 Variable *T = makeReg(Dest->getType()); | 3429 Variable *T = makeReg(Dest->getType()); |
3443 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3430 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
3444 _mov(Dest, T); | 3431 _mov(Dest, T); |
3445 UnimplementedError(Func->getContext()->getFlags()); | 3432 UnimplementedError(Func->getContext()->getFlags()); |
3446 } else if (Dest->getType() == IceType_i64) { | 3433 } else if (Dest->getType() == IceType_i64) { |
3447 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 | 3434 // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 |
3448 Constant *ShiftAmt = Ctx->getConstantInt32(31); | 3435 Constant *ShiftAmt = Ctx->getConstantInt32(31); |
3449 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 3436 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
3450 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 3437 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
3451 Variable *T_Lo = makeReg(DestLo->getType()); | 3438 Variable *T_Lo = makeReg(DestLo->getType()); |
3452 if (Src0->getType() == IceType_i32) { | 3439 if (Src0->getType() == IceType_i32) { |
3453 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 3440 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
(...skipping 27 matching lines...) Expand all Loading... |
3481 Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1); | 3468 Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1); |
3482 Variable *T = makeReg(Dest->getType()); | 3469 Variable *T = makeReg(Dest->getType()); |
3483 lowerInt1ForSelect(T, Src0, _m1, _0); | 3470 lowerInt1ForSelect(T, Src0, _m1, _0); |
3484 _mov(Dest, T); | 3471 _mov(Dest, T); |
3485 } | 3472 } |
3486 break; | 3473 break; |
3487 } | 3474 } |
3488 case InstCast::Zext: { | 3475 case InstCast::Zext: { |
3489 if (isVectorType(Dest->getType())) { | 3476 if (isVectorType(Dest->getType())) { |
3490 Variable *T = makeReg(Dest->getType()); | 3477 Variable *T = makeReg(Dest->getType()); |
3491 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3478 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
3492 _mov(Dest, T); | 3479 _mov(Dest, T); |
3493 UnimplementedError(Func->getContext()->getFlags()); | 3480 UnimplementedError(Func->getContext()->getFlags()); |
3494 } else if (Dest->getType() == IceType_i64) { | 3481 } else if (Dest->getType() == IceType_i64) { |
3495 // t1=uxtb src; dst.lo=t1; dst.hi=0 | 3482 // t1=uxtb src; dst.lo=t1; dst.hi=0 |
3496 Operand *_0 = | 3483 Operand *_0 = |
3497 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 3484 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
3498 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 3485 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
3499 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 3486 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
3500 Variable *T_Lo = makeReg(DestLo->getType()); | 3487 Variable *T_Lo = makeReg(DestLo->getType()); |
3501 | 3488 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3537 Variable *Src0R = legalizeToReg(Src0); | 3524 Variable *Src0R = legalizeToReg(Src0); |
3538 Variable *T = makeReg(Dest->getType()); | 3525 Variable *T = makeReg(Dest->getType()); |
3539 _uxt(T, Src0R); | 3526 _uxt(T, Src0R); |
3540 _mov(Dest, T); | 3527 _mov(Dest, T); |
3541 } | 3528 } |
3542 break; | 3529 break; |
3543 } | 3530 } |
3544 case InstCast::Trunc: { | 3531 case InstCast::Trunc: { |
3545 if (isVectorType(Dest->getType())) { | 3532 if (isVectorType(Dest->getType())) { |
3546 Variable *T = makeReg(Dest->getType()); | 3533 Variable *T = makeReg(Dest->getType()); |
3547 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3534 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
3548 _mov(Dest, T); | 3535 _mov(Dest, T); |
3549 UnimplementedError(Func->getContext()->getFlags()); | 3536 UnimplementedError(Func->getContext()->getFlags()); |
3550 } else { | 3537 } else { |
3551 if (Src0->getType() == IceType_i64) | 3538 if (Src0->getType() == IceType_i64) |
3552 Src0 = loOperand(Src0); | 3539 Src0 = loOperand(Src0); |
3553 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 3540 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
3554 // t1 = trunc Src0RF; Dest = t1 | 3541 // t1 = trunc Src0RF; Dest = t1 |
3555 Variable *T = makeReg(Dest->getType()); | 3542 Variable *T = makeReg(Dest->getType()); |
3556 _mov(T, Src0RF); | 3543 _mov(T, Src0RF); |
3557 if (Dest->getType() == IceType_i1) | 3544 if (Dest->getType() == IceType_i1) |
3558 _and(T, T, Ctx->getConstantInt1(1)); | 3545 _and(T, T, Ctx->getConstantInt1(1)); |
3559 _mov(Dest, T); | 3546 _mov(Dest, T); |
3560 } | 3547 } |
3561 break; | 3548 break; |
3562 } | 3549 } |
3563 case InstCast::Fptrunc: | 3550 case InstCast::Fptrunc: |
3564 case InstCast::Fpext: { | 3551 case InstCast::Fpext: { |
3565 // fptrunc: dest.f32 = fptrunc src0.fp64 | 3552 // fptrunc: dest.f32 = fptrunc src0.fp64 |
3566 // fpext: dest.f64 = fptrunc src0.fp32 | 3553 // fpext: dest.f64 = fptrunc src0.fp32 |
3567 const bool IsTrunc = CastKind == InstCast::Fptrunc; | 3554 const bool IsTrunc = CastKind == InstCast::Fptrunc; |
3568 if (isVectorType(Dest->getType())) { | 3555 if (isVectorType(Dest->getType())) { |
3569 Variable *T = makeReg(Dest->getType()); | 3556 Variable *T = makeReg(Dest->getType()); |
3570 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3557 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
3571 _mov(Dest, T); | 3558 _mov(Dest, T); |
3572 UnimplementedError(Func->getContext()->getFlags()); | 3559 UnimplementedError(Func->getContext()->getFlags()); |
3573 break; | 3560 break; |
3574 } | 3561 } |
3575 assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); | 3562 assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); |
3576 assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); | 3563 assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); |
3577 Variable *Src0R = legalizeToReg(Src0); | 3564 Variable *Src0R = legalizeToReg(Src0); |
3578 Variable *T = makeReg(Dest->getType()); | 3565 Variable *T = makeReg(Dest->getType()); |
3579 _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); | 3566 _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); |
3580 _mov(Dest, T); | 3567 _mov(Dest, T); |
3581 break; | 3568 break; |
3582 } | 3569 } |
3583 case InstCast::Fptosi: | 3570 case InstCast::Fptosi: |
3584 case InstCast::Fptoui: { | 3571 case InstCast::Fptoui: { |
3585 if (isVectorType(Dest->getType())) { | 3572 if (isVectorType(Dest->getType())) { |
3586 Variable *T = makeReg(Dest->getType()); | 3573 Variable *T = makeReg(Dest->getType()); |
3587 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3574 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
3588 _mov(Dest, T); | 3575 _mov(Dest, T); |
3589 UnimplementedError(Func->getContext()->getFlags()); | 3576 UnimplementedError(Func->getContext()->getFlags()); |
3590 break; | 3577 break; |
3591 } | 3578 } |
3592 | 3579 |
3593 const bool DestIsSigned = CastKind == InstCast::Fptosi; | 3580 const bool DestIsSigned = CastKind == InstCast::Fptosi; |
3594 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); | 3581 const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); |
3595 if (llvm::isa<Variable64On32>(Dest)) { | 3582 if (llvm::isa<Variable64On32>(Dest)) { |
3596 llvm::report_fatal_error("fp-to-i64 should have been pre-lowered."); | 3583 llvm::report_fatal_error("fp-to-i64 should have been pre-lowered."); |
3597 } | 3584 } |
(...skipping 18 matching lines...) Expand all Loading... |
3616 lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); | 3603 lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); |
3617 T = T_1; | 3604 T = T_1; |
3618 } | 3605 } |
3619 _mov(Dest, T); | 3606 _mov(Dest, T); |
3620 break; | 3607 break; |
3621 } | 3608 } |
3622 case InstCast::Sitofp: | 3609 case InstCast::Sitofp: |
3623 case InstCast::Uitofp: { | 3610 case InstCast::Uitofp: { |
3624 if (isVectorType(Dest->getType())) { | 3611 if (isVectorType(Dest->getType())) { |
3625 Variable *T = makeReg(Dest->getType()); | 3612 Variable *T = makeReg(Dest->getType()); |
3626 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3613 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
3627 _mov(Dest, T); | 3614 _mov(Dest, T); |
3628 UnimplementedError(Func->getContext()->getFlags()); | 3615 UnimplementedError(Func->getContext()->getFlags()); |
3629 break; | 3616 break; |
3630 } | 3617 } |
3631 const bool SourceIsSigned = CastKind == InstCast::Sitofp; | 3618 const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
3632 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); | 3619 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); |
3633 if (Src0->getType() == IceType_i64) { | 3620 if (Src0->getType() == IceType_i64) { |
3634 llvm::report_fatal_error("i64-to-fp should have been pre-lowered."); | 3621 llvm::report_fatal_error("i64-to-fp should have been pre-lowered."); |
3635 } | 3622 } |
3636 // sitofp: | 3623 // sitofp: |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3693 case IceType_i64: { | 3680 case IceType_i64: { |
3694 // t0, t1 <- src0 | 3681 // t0, t1 <- src0 |
3695 // dest[31..0] = t0 | 3682 // dest[31..0] = t0 |
3696 // dest[63..32] = t1 | 3683 // dest[63..32] = t1 |
3697 assert(Src0->getType() == IceType_f64); | 3684 assert(Src0->getType() == IceType_f64); |
3698 auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); | 3685 auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
3699 T->initHiLo(Func); | 3686 T->initHiLo(Func); |
3700 configureBitcastTemporary(T); | 3687 configureBitcastTemporary(T); |
3701 Variable *Src0R = legalizeToReg(Src0); | 3688 Variable *Src0R = legalizeToReg(Src0); |
3702 _mov(T, Src0R); | 3689 _mov(T, Src0R); |
3703 Context.insert(InstFakeUse::create(Func, T->getHi())); | 3690 Context.insert<InstFakeUse>(T->getHi()); |
3704 Context.insert(InstFakeUse::create(Func, T->getLo())); | 3691 Context.insert<InstFakeUse>(T->getLo()); |
3705 lowerAssign(InstAssign::create(Func, Dest, T)); | 3692 lowerAssign(InstAssign::create(Func, Dest, T)); |
3706 break; | 3693 break; |
3707 } | 3694 } |
3708 case IceType_f64: { | 3695 case IceType_f64: { |
3709 // T0 <- lo(src) | 3696 // T0 <- lo(src) |
3710 // T1 <- hi(src) | 3697 // T1 <- hi(src) |
3711 // vmov T2, T0, T1 | 3698 // vmov T2, T0, T1 |
3712 // Dest <- T2 | 3699 // Dest <- T2 |
3713 assert(Src0->getType() == IceType_i64); | 3700 assert(Src0->getType() == IceType_i64); |
3714 Variable *T = makeReg(DestType); | 3701 Variable *T = makeReg(DestType); |
3715 auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); | 3702 auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
3716 Src64->initHiLo(Func); | 3703 Src64->initHiLo(Func); |
3717 configureBitcastTemporary(Src64); | 3704 configureBitcastTemporary(Src64); |
3718 lowerAssign(InstAssign::create(Func, Src64, Src0)); | 3705 lowerAssign(InstAssign::create(Func, Src64, Src0)); |
3719 _mov(T, Src64); | 3706 _mov(T, Src64); |
3720 lowerAssign(InstAssign::create(Func, Dest, T)); | 3707 lowerAssign(InstAssign::create(Func, Dest, T)); |
3721 break; | 3708 break; |
3722 } | 3709 } |
3723 case IceType_v4i1: | 3710 case IceType_v4i1: |
3724 case IceType_v8i1: | 3711 case IceType_v8i1: |
3725 case IceType_v16i1: | 3712 case IceType_v16i1: |
3726 case IceType_v8i16: | 3713 case IceType_v8i16: |
3727 case IceType_v16i8: | 3714 case IceType_v16i8: |
3728 case IceType_v4f32: | 3715 case IceType_v4f32: |
3729 case IceType_v4i32: { | 3716 case IceType_v4i32: { |
3730 // avoid liveness errors | 3717 // avoid liveness errors |
3731 Variable *T = makeReg(DestType); | 3718 Variable *T = makeReg(DestType); |
3732 Context.insert(InstFakeDef::create(Func, T, legalizeToReg(Src0))); | 3719 Context.insert<InstFakeDef>(T, legalizeToReg(Src0)); |
3733 _mov(Dest, T); | 3720 _mov(Dest, T); |
3734 UnimplementedError(Func->getContext()->getFlags()); | 3721 UnimplementedError(Func->getContext()->getFlags()); |
3735 break; | 3722 break; |
3736 } | 3723 } |
3737 } | 3724 } |
3738 break; | 3725 break; |
3739 } | 3726 } |
3740 } | 3727 } |
3741 } | 3728 } |
3742 | 3729 |
3743 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { | 3730 void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { |
3744 Variable *Dest = Inst->getDest(); | 3731 Variable *Dest = Inst->getDest(); |
3745 Type DestType = Dest->getType(); | 3732 Type DestType = Dest->getType(); |
3746 Variable *T = makeReg(DestType); | 3733 Variable *T = makeReg(DestType); |
3747 Context.insert(InstFakeDef::create(Func, T)); | 3734 Context.insert<InstFakeDef>(T); |
3748 _mov(Dest, T); | 3735 _mov(Dest, T); |
3749 UnimplementedError(Func->getContext()->getFlags()); | 3736 UnimplementedError(Func->getContext()->getFlags()); |
3750 } | 3737 } |
3751 | 3738 |
3752 namespace { | 3739 namespace { |
3753 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering | 3740 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering |
3754 // (and naming). | 3741 // (and naming). |
3755 enum { | 3742 enum { |
3756 #define X(val, CC0, CC1) _fcmp_ll_##val, | 3743 #define X(val, CC0, CC1) _fcmp_ll_##val, |
3757 FCMPARM32_TABLE | 3744 FCMPARM32_TABLE |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3819 assert(Condition < llvm::array_lengthof(TableFcmp)); | 3806 assert(Condition < llvm::array_lengthof(TableFcmp)); |
3820 return CondWhenTrue(TableFcmp[Condition].CC0, TableFcmp[Condition].CC1); | 3807 return CondWhenTrue(TableFcmp[Condition].CC0, TableFcmp[Condition].CC1); |
3821 } | 3808 } |
3822 } | 3809 } |
3823 } | 3810 } |
3824 | 3811 |
3825 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { | 3812 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { |
3826 Variable *Dest = Instr->getDest(); | 3813 Variable *Dest = Instr->getDest(); |
3827 if (isVectorType(Dest->getType())) { | 3814 if (isVectorType(Dest->getType())) { |
3828 Variable *T = makeReg(Dest->getType()); | 3815 Variable *T = makeReg(Dest->getType()); |
3829 Context.insert(InstFakeDef::create(Func, T)); | 3816 Context.insert<InstFakeDef>(T); |
3830 _mov(Dest, T); | 3817 _mov(Dest, T); |
3831 UnimplementedError(Func->getContext()->getFlags()); | 3818 UnimplementedError(Func->getContext()->getFlags()); |
3832 return; | 3819 return; |
3833 } | 3820 } |
3834 | 3821 |
3835 Variable *T = makeReg(IceType_i1); | 3822 Variable *T = makeReg(IceType_i1); |
3836 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); | 3823 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
3837 Operand *_0 = | 3824 Operand *_0 = |
3838 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 3825 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
3839 | 3826 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3877 if (SrcsLo.hasConstOperand()) { | 3864 if (SrcsLo.hasConstOperand()) { |
3878 const uint32_t ValueLo = SrcsLo.getConstantValue(); | 3865 const uint32_t ValueLo = SrcsLo.getConstantValue(); |
3879 const uint32_t ValueHi = SrcsHi.getConstantValue(); | 3866 const uint32_t ValueHi = SrcsHi.getConstantValue(); |
3880 const uint64_t Value = (static_cast<uint64_t>(ValueHi) << 32) | ValueLo; | 3867 const uint64_t Value = (static_cast<uint64_t>(ValueHi) << 32) | ValueLo; |
3881 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && | 3868 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && |
3882 Value == 0) { | 3869 Value == 0) { |
3883 Variable *T = makeReg(IceType_i32); | 3870 Variable *T = makeReg(IceType_i32); |
3884 Variable *Src0LoR = SrcsLo.src0R(this); | 3871 Variable *Src0LoR = SrcsLo.src0R(this); |
3885 Variable *Src0HiR = SrcsHi.src0R(this); | 3872 Variable *Src0HiR = SrcsHi.src0R(this); |
3886 _orrs(T, Src0LoR, Src0HiR); | 3873 _orrs(T, Src0LoR, Src0HiR); |
3887 Context.insert(InstFakeUse::create(Func, T)); | 3874 Context.insert<InstFakeUse>(T); |
3888 return CondWhenTrue(TableIcmp64[Index].C1); | 3875 return CondWhenTrue(TableIcmp64[Index].C1); |
3889 } | 3876 } |
3890 | 3877 |
3891 Variable *Src0RLo = SrcsLo.src0R(this); | 3878 Variable *Src0RLo = SrcsLo.src0R(this); |
3892 Variable *Src0RHi = SrcsHi.src0R(this); | 3879 Variable *Src0RHi = SrcsHi.src0R(this); |
3893 Operand *Src1RFLo = SrcsLo.src1RF(this); | 3880 Operand *Src1RFLo = SrcsLo.src1RF(this); |
3894 Operand *Src1RFHi = ValueLo == ValueHi ? Src1RFLo : SrcsHi.src1RF(this); | 3881 Operand *Src1RFHi = ValueLo == ValueHi ? Src1RFLo : SrcsHi.src1RF(this); |
3895 | 3882 |
3896 const bool UseRsb = TableIcmp64[Index].Swapped != SrcsLo.swappedOperands(); | 3883 const bool UseRsb = TableIcmp64[Index].Swapped != SrcsLo.swappedOperands(); |
3897 | 3884 |
3898 if (UseRsb) { | 3885 if (UseRsb) { |
3899 if (TableIcmp64[Index].IsSigned) { | 3886 if (TableIcmp64[Index].IsSigned) { |
3900 Variable *T = makeReg(IceType_i32); | 3887 Variable *T = makeReg(IceType_i32); |
3901 _rsbs(T, Src0RLo, Src1RFLo); | 3888 _rsbs(T, Src0RLo, Src1RFLo); |
3902 Context.insert(InstFakeUse::create(Func, T)); | 3889 Context.insert<InstFakeUse>(T); |
3903 | 3890 |
3904 T = makeReg(IceType_i32); | 3891 T = makeReg(IceType_i32); |
3905 _rscs(T, Src0RHi, Src1RFHi); | 3892 _rscs(T, Src0RHi, Src1RFHi); |
3906 // We need to add a FakeUse here because liveness gets mad at us (Def | 3893 // We need to add a FakeUse here because liveness gets mad at us (Def |
3907 // without Use.) Note that flag-setting instructions are considered to | 3894 // without Use.) Note that flag-setting instructions are considered to |
3908 // have side effects and, therefore, are not DCE'ed. | 3895 // have side effects and, therefore, are not DCE'ed. |
3909 Context.insert(InstFakeUse::create(Func, T)); | 3896 Context.insert<InstFakeUse>(T); |
3910 } else { | 3897 } else { |
3911 Variable *T = makeReg(IceType_i32); | 3898 Variable *T = makeReg(IceType_i32); |
3912 _rsbs(T, Src0RHi, Src1RFHi); | 3899 _rsbs(T, Src0RHi, Src1RFHi); |
3913 Context.insert(InstFakeUse::create(Func, T)); | 3900 Context.insert<InstFakeUse>(T); |
3914 | 3901 |
3915 T = makeReg(IceType_i32); | 3902 T = makeReg(IceType_i32); |
3916 _rsbs(T, Src0RLo, Src1RFLo, CondARM32::EQ); | 3903 _rsbs(T, Src0RLo, Src1RFLo, CondARM32::EQ); |
3917 Context.insert(InstFakeUse::create(Func, T)); | 3904 Context.insert<InstFakeUse>(T); |
3918 } | 3905 } |
3919 } else { | 3906 } else { |
3920 if (TableIcmp64[Index].IsSigned) { | 3907 if (TableIcmp64[Index].IsSigned) { |
3921 _cmp(Src0RLo, Src1RFLo); | 3908 _cmp(Src0RLo, Src1RFLo); |
3922 Variable *T = makeReg(IceType_i32); | 3909 Variable *T = makeReg(IceType_i32); |
3923 _sbcs(T, Src0RHi, Src1RFHi); | 3910 _sbcs(T, Src0RHi, Src1RFHi); |
3924 Context.insert(InstFakeUse::create(Func, T)); | 3911 Context.insert<InstFakeUse>(T); |
3925 } else { | 3912 } else { |
3926 _cmp(Src0RHi, Src1RFHi); | 3913 _cmp(Src0RHi, Src1RFHi); |
3927 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); | 3914 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); |
3928 } | 3915 } |
3929 } | 3916 } |
3930 | 3917 |
3931 return CondWhenTrue(TableIcmp64[Index].C1); | 3918 return CondWhenTrue(TableIcmp64[Index].C1); |
3932 } | 3919 } |
3933 | 3920 |
3934 Variable *Src0RLo, *Src0RHi; | 3921 Variable *Src0RLo, *Src0RHi; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3973 // longer sequence. | 3960 // longer sequence. |
3974 // | 3961 // |
3975 // So, we are going with the GCC version since it's usually better (except | 3962 // So, we are going with the GCC version since it's usually better (except |
3976 // perhaps for eq/ne). We could revisit special-casing eq/ne later. | 3963 // perhaps for eq/ne). We could revisit special-casing eq/ne later. |
3977 if (TableIcmp64[Index].IsSigned) { | 3964 if (TableIcmp64[Index].IsSigned) { |
3978 Variable *ScratchReg = makeReg(IceType_i32); | 3965 Variable *ScratchReg = makeReg(IceType_i32); |
3979 _cmp(Src0RLo, Src1RFLo); | 3966 _cmp(Src0RLo, Src1RFLo); |
3980 _sbcs(ScratchReg, Src0RHi, Src1RFHi); | 3967 _sbcs(ScratchReg, Src0RHi, Src1RFHi); |
3981 // ScratchReg isn't going to be used, but we need the side-effect of | 3968 // ScratchReg isn't going to be used, but we need the side-effect of |
3982 // setting flags from this operation. | 3969 // setting flags from this operation. |
3983 Context.insert(InstFakeUse::create(Func, ScratchReg)); | 3970 Context.insert<InstFakeUse>(ScratchReg); |
3984 } else { | 3971 } else { |
3985 _cmp(Src0RHi, Src1RFHi); | 3972 _cmp(Src0RHi, Src1RFHi); |
3986 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); | 3973 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); |
3987 } | 3974 } |
3988 return CondWhenTrue(TableIcmp64[Index].C1); | 3975 return CondWhenTrue(TableIcmp64[Index].C1); |
3989 } | 3976 } |
3990 | 3977 |
3991 TargetARM32::CondWhenTrue | 3978 TargetARM32::CondWhenTrue |
3992 TargetARM32::lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, | 3979 TargetARM32::lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
3993 Operand *Src1) { | 3980 Operand *Src1) { |
(...skipping 19 matching lines...) Expand all Loading... |
4013 _cmn(Src0R, Src1F); | 4000 _cmn(Src0R, Src1F); |
4014 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4001 return CondWhenTrue(getIcmp32Mapping(Condition)); |
4015 } | 4002 } |
4016 | 4003 |
4017 Operand *Src1RF = Srcs.src1RF(this); | 4004 Operand *Src1RF = Srcs.src1RF(this); |
4018 if (!Srcs.swappedOperands()) { | 4005 if (!Srcs.swappedOperands()) { |
4019 _cmp(Src0R, Src1RF); | 4006 _cmp(Src0R, Src1RF); |
4020 } else { | 4007 } else { |
4021 Variable *T = makeReg(IceType_i32); | 4008 Variable *T = makeReg(IceType_i32); |
4022 _rsbs(T, Src0R, Src1RF); | 4009 _rsbs(T, Src0R, Src1RF); |
4023 Context.insert(InstFakeUse::create(Func, T)); | 4010 Context.insert<InstFakeUse>(T); |
4024 } | 4011 } |
4025 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4012 return CondWhenTrue(getIcmp32Mapping(Condition)); |
4026 } | 4013 } |
4027 | 4014 |
4028 TargetARM32::CondWhenTrue | 4015 TargetARM32::CondWhenTrue |
4029 TargetARM32::lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, Operand *Src0, | 4016 TargetARM32::lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
4030 Operand *Src1) { | 4017 Operand *Src1) { |
4031 Int32Operands Srcs(Src0, Src1); | 4018 Int32Operands Srcs(Src0, Src1); |
4032 const int32_t ShAmt = 32 - getScalarIntBitWidth(Src0->getType()); | 4019 const int32_t ShAmt = 32 - getScalarIntBitWidth(Src0->getType()); |
4033 assert(ShAmt >= 0); | 4020 assert(ShAmt >= 0); |
4034 | 4021 |
4035 if (!Srcs.hasConstOperand()) { | 4022 if (!Srcs.hasConstOperand()) { |
4036 Variable *Src0R = makeReg(IceType_i32); | 4023 Variable *Src0R = makeReg(IceType_i32); |
4037 Operand *ShAmtImm = shAmtImm(ShAmt); | 4024 Operand *ShAmtImm = shAmtImm(ShAmt); |
4038 _lsl(Src0R, legalizeToReg(Src0), ShAmtImm); | 4025 _lsl(Src0R, legalizeToReg(Src0), ShAmtImm); |
4039 | 4026 |
4040 Variable *Src1R = legalizeToReg(Src1); | 4027 Variable *Src1R = legalizeToReg(Src1); |
4041 auto *Src1F = OperandARM32FlexReg::create(Func, IceType_i32, Src1R, | 4028 auto *Src1F = OperandARM32FlexReg::create(Func, IceType_i32, Src1R, |
4042 OperandARM32::LSL, ShAmtImm); | 4029 OperandARM32::LSL, ShAmtImm); |
4043 _cmp(Src0R, Src1F); | 4030 _cmp(Src0R, Src1F); |
4044 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4031 return CondWhenTrue(getIcmp32Mapping(Condition)); |
4045 } | 4032 } |
4046 | 4033 |
4047 const int32_t Value = Srcs.getConstantValue(); | 4034 const int32_t Value = Srcs.getConstantValue(); |
4048 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && Value == 0) { | 4035 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && Value == 0) { |
4049 Operand *ShAmtImm = shAmtImm(ShAmt); | 4036 Operand *ShAmtImm = shAmtImm(ShAmt); |
4050 Variable *T = makeReg(IceType_i32); | 4037 Variable *T = makeReg(IceType_i32); |
4051 _lsls(T, Srcs.src0R(this), ShAmtImm); | 4038 _lsls(T, Srcs.src0R(this), ShAmtImm); |
4052 Context.insert(InstFakeUse::create(Func, T)); | 4039 Context.insert<InstFakeUse>(T); |
4053 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4040 return CondWhenTrue(getIcmp32Mapping(Condition)); |
4054 } | 4041 } |
4055 | 4042 |
4056 Variable *ConstR = makeReg(IceType_i32); | 4043 Variable *ConstR = makeReg(IceType_i32); |
4057 _mov(ConstR, | 4044 _mov(ConstR, |
4058 legalize(Ctx->getConstantInt32(Value << ShAmt), Legal_Reg | Legal_Flex)); | 4045 legalize(Ctx->getConstantInt32(Value << ShAmt), Legal_Reg | Legal_Flex)); |
4059 Operand *NonConstF = OperandARM32FlexReg::create( | 4046 Operand *NonConstF = OperandARM32FlexReg::create( |
4060 Func, IceType_i32, Srcs.src0R(this), OperandARM32::LSL, | 4047 Func, IceType_i32, Srcs.src0R(this), OperandARM32::LSL, |
4061 Ctx->getConstantInt32(ShAmt)); | 4048 Ctx->getConstantInt32(ShAmt)); |
4062 | 4049 |
4063 if (Srcs.swappedOperands()) { | 4050 if (Srcs.swappedOperands()) { |
4064 _cmp(ConstR, NonConstF); | 4051 _cmp(ConstR, NonConstF); |
4065 } else { | 4052 } else { |
4066 Variable *T = makeReg(IceType_i32); | 4053 Variable *T = makeReg(IceType_i32); |
4067 _rsbs(T, ConstR, NonConstF); | 4054 _rsbs(T, ConstR, NonConstF); |
4068 Context.insert(InstFakeUse::create(Func, T)); | 4055 Context.insert<InstFakeUse>(T); |
4069 } | 4056 } |
4070 return CondWhenTrue(getIcmp32Mapping(Condition)); | 4057 return CondWhenTrue(getIcmp32Mapping(Condition)); |
4071 } | 4058 } |
4072 | 4059 |
4073 TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(const InstIcmp *Inst) { | 4060 TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(const InstIcmp *Inst) { |
4074 assert(Inst->getSrc(0)->getType() != IceType_i1); | 4061 assert(Inst->getSrc(0)->getType() != IceType_i1); |
4075 assert(Inst->getSrc(1)->getType() != IceType_i1); | 4062 assert(Inst->getSrc(1)->getType() != IceType_i1); |
4076 | 4063 |
4077 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 4064 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
4078 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | 4065 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4118 case IceType_i64: | 4105 case IceType_i64: |
4119 return lowerInt64IcmpCond(Condition, Src0, Src1); | 4106 return lowerInt64IcmpCond(Condition, Src0, Src1); |
4120 } | 4107 } |
4121 } | 4108 } |
4122 | 4109 |
4123 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { | 4110 void TargetARM32::lowerIcmp(const InstIcmp *Inst) { |
4124 Variable *Dest = Inst->getDest(); | 4111 Variable *Dest = Inst->getDest(); |
4125 | 4112 |
4126 if (isVectorType(Dest->getType())) { | 4113 if (isVectorType(Dest->getType())) { |
4127 Variable *T = makeReg(Dest->getType()); | 4114 Variable *T = makeReg(Dest->getType()); |
4128 Context.insert(InstFakeDef::create(Func, T)); | 4115 Context.insert<InstFakeDef>(T); |
4129 _mov(Dest, T); | 4116 _mov(Dest, T); |
4130 UnimplementedError(Func->getContext()->getFlags()); | 4117 UnimplementedError(Func->getContext()->getFlags()); |
4131 return; | 4118 return; |
4132 } | 4119 } |
4133 | 4120 |
4134 Operand *_0 = | 4121 Operand *_0 = |
4135 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 4122 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
4136 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); | 4123 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
4137 Variable *T = makeReg(IceType_i1); | 4124 Variable *T = makeReg(IceType_i1); |
4138 | 4125 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4212 ValueReg = makeReg(DestTy); | 4199 ValueReg = makeReg(DestTy); |
4213 ValueHiReg = nullptr; | 4200 ValueHiReg = nullptr; |
4214 ValueLoReg = ValueReg; | 4201 ValueLoReg = ValueReg; |
4215 | 4202 |
4216 TmpReg = makeReg(DestTy); | 4203 TmpReg = makeReg(DestTy); |
4217 TmpHiReg = nullptr; | 4204 TmpHiReg = nullptr; |
4218 TmpLoReg = TmpReg; | 4205 TmpLoReg = TmpReg; |
4219 } | 4206 } |
4220 | 4207 |
4221 if (DestTy == IceType_i64) { | 4208 if (DestTy == IceType_i64) { |
4222 Context.insert(InstFakeDef::create(Func, Value)); | 4209 Context.insert<InstFakeDef>(Value); |
4223 } | 4210 } |
4224 lowerAssign(InstAssign::create(Func, Value, Val)); | 4211 lowerAssign(InstAssign::create(Func, Value, Val)); |
4225 | 4212 |
4226 Variable *PtrVar = Func->makeVariable(IceType_i32); | 4213 Variable *PtrVar = Func->makeVariable(IceType_i32); |
4227 lowerAssign(InstAssign::create(Func, PtrVar, Ptr)); | 4214 lowerAssign(InstAssign::create(Func, PtrVar, Ptr)); |
4228 | 4215 |
4229 _dmb(); | 4216 _dmb(); |
4230 Context.insert(Retry); | 4217 Context.insert(Retry); |
4231 Mem = formMemoryOperand(PtrVar, DestTy); | 4218 Mem = formMemoryOperand(PtrVar, DestTy); |
4232 if (DestTy == IceType_i64) { | 4219 if (DestTy == IceType_i64) { |
4233 Context.insert(InstFakeDef::create(Func, ValueReg, Value)); | 4220 Context.insert<InstFakeDef>(ValueReg, Value); |
4234 } | 4221 } |
4235 lowerAssign(InstAssign::create(Func, ValueReg, Value)); | 4222 lowerAssign(InstAssign::create(Func, ValueReg, Value)); |
4236 if (DestTy == IceType_i8 || DestTy == IceType_i16) { | 4223 if (DestTy == IceType_i8 || DestTy == IceType_i16) { |
4237 _uxt(ValueReg, ValueReg); | 4224 _uxt(ValueReg, ValueReg); |
4238 } | 4225 } |
4239 _ldrex(PtrContentsReg, Mem); | 4226 _ldrex(PtrContentsReg, Mem); |
4240 | 4227 |
4241 if (DestTy == IceType_i64) { | 4228 if (DestTy == IceType_i64) { |
4242 Context.insert(InstFakeDef::create(Func, TmpReg, ValueReg)); | 4229 Context.insert<InstFakeDef>(TmpReg, ValueReg); |
4243 } | 4230 } |
4244 switch (Operation) { | 4231 switch (Operation) { |
4245 default: | 4232 default: |
4246 Func->setError("Unknown AtomicRMW operation"); | 4233 Func->setError("Unknown AtomicRMW operation"); |
4247 return; | 4234 return; |
4248 case Intrinsics::AtomicAdd: | 4235 case Intrinsics::AtomicAdd: |
4249 if (DestTy == IceType_i64) { | 4236 if (DestTy == IceType_i64) { |
4250 _adds(TmpLoReg, PtrContentsLoReg, ValueLoReg); | 4237 _adds(TmpLoReg, PtrContentsLoReg, ValueLoReg); |
4251 _adc(TmpHiReg, PtrContentsHiReg, ValueHiReg); | 4238 _adc(TmpHiReg, PtrContentsHiReg, ValueHiReg); |
4252 } else { | 4239 } else { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4286 } | 4273 } |
4287 break; | 4274 break; |
4288 } | 4275 } |
4289 _strex(Success, TmpReg, Mem); | 4276 _strex(Success, TmpReg, Mem); |
4290 _cmp(Success, _0); | 4277 _cmp(Success, _0); |
4291 _br(Retry, CondARM32::NE); | 4278 _br(Retry, CondARM32::NE); |
4292 | 4279 |
4293 // The following fake-uses ensure that Subzero will not clobber them in the | 4280 // The following fake-uses ensure that Subzero will not clobber them in the |
4294 // load-linked/store-conditional loop above. We might have to spill them, but | 4281 // load-linked/store-conditional loop above. We might have to spill them, but |
4295 // spilling is preferable over incorrect behavior. | 4282 // spilling is preferable over incorrect behavior. |
4296 Context.insert(InstFakeUse::create(Func, PtrVar)); | 4283 Context.insert<InstFakeUse>(PtrVar); |
4297 if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) { | 4284 if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) { |
4298 Context.insert(InstFakeUse::create(Func, Value64->getHi())); | 4285 Context.insert<InstFakeUse>(Value64->getHi()); |
4299 Context.insert(InstFakeUse::create(Func, Value64->getLo())); | 4286 Context.insert<InstFakeUse>(Value64->getLo()); |
4300 } else { | 4287 } else { |
4301 Context.insert(InstFakeUse::create(Func, Value)); | 4288 Context.insert<InstFakeUse>(Value); |
4302 } | 4289 } |
4303 _dmb(); | 4290 _dmb(); |
4304 if (DestTy == IceType_i8 || DestTy == IceType_i16) { | 4291 if (DestTy == IceType_i8 || DestTy == IceType_i16) { |
4305 _uxt(PtrContentsReg, PtrContentsReg); | 4292 _uxt(PtrContentsReg, PtrContentsReg); |
4306 } | 4293 } |
4307 | 4294 |
4308 if (DestTy == IceType_i64) { | 4295 if (DestTy == IceType_i64) { |
4309 Context.insert(InstFakeUse::create(Func, PtrContentsReg)); | 4296 Context.insert<InstFakeUse>(PtrContentsReg); |
4310 } | 4297 } |
4311 lowerAssign(InstAssign::create(Func, Dest, PtrContentsReg)); | 4298 lowerAssign(InstAssign::create(Func, Dest, PtrContentsReg)); |
4312 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { | 4299 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { |
4313 Context.insert(InstFakeUse::create(Func, Dest64->getLo())); | 4300 Context.insert<InstFakeUse>(Dest64->getLo()); |
4314 Context.insert(InstFakeUse::create(Func, Dest64->getHi())); | 4301 Context.insert<InstFakeUse>(Dest64->getHi()); |
4315 } else { | 4302 } else { |
4316 Context.insert(InstFakeUse::create(Func, Dest)); | 4303 Context.insert<InstFakeUse>(Dest); |
4317 } | 4304 } |
4318 } | 4305 } |
4319 | 4306 |
4320 void TargetARM32::postambleCtpop64(const InstCall *Instr) { | 4307 void TargetARM32::postambleCtpop64(const InstCall *Instr) { |
4321 Operand *Arg0 = Instr->getArg(0); | 4308 Operand *Arg0 = Instr->getArg(0); |
4322 if (isInt32Asserting32Or64(Arg0->getType())) { | 4309 if (isInt32Asserting32Or64(Arg0->getType())) { |
4323 return; | 4310 return; |
4324 } | 4311 } |
4325 // The popcount helpers always return 32-bit values, while the intrinsic's | 4312 // The popcount helpers always return 32-bit values, while the intrinsic's |
4326 // signature matches some 64-bit platform's native instructions and expect to | 4313 // signature matches some 64-bit platform's native instructions and expect to |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4384 _ldrex(T, formMemoryOperand(Instr->getArg(0), IceType_i64)); | 4371 _ldrex(T, formMemoryOperand(Instr->getArg(0), IceType_i64)); |
4385 } else { | 4372 } else { |
4386 T = makeReg(DestTy); | 4373 T = makeReg(DestTy); |
4387 _ldr(T, formMemoryOperand(Instr->getArg(0), DestTy)); | 4374 _ldr(T, formMemoryOperand(Instr->getArg(0), DestTy)); |
4388 } | 4375 } |
4389 _dmb(); | 4376 _dmb(); |
4390 lowerAssign(InstAssign::create(Func, Dest, T)); | 4377 lowerAssign(InstAssign::create(Func, Dest, T)); |
4391 // Make sure the atomic load isn't elided when unused, by adding a FakeUse. | 4378 // Make sure the atomic load isn't elided when unused, by adding a FakeUse. |
4392 // Since lowerLoad may fuse the load w/ an arithmetic instruction, insert | 4379 // Since lowerLoad may fuse the load w/ an arithmetic instruction, insert |
4393 // the FakeUse on the last-inserted instruction's dest. | 4380 // the FakeUse on the last-inserted instruction's dest. |
4394 Context.insert( | 4381 Context.insert<InstFakeUse>(Context.getLastInserted()->getDest()); |
4395 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | |
4396 return; | 4382 return; |
4397 } | 4383 } |
4398 case Intrinsics::AtomicStore: { | 4384 case Intrinsics::AtomicStore: { |
4399 // We require the memory address to be naturally aligned. Given that is the | 4385 // We require the memory address to be naturally aligned. Given that is the |
4400 // case, then normal loads are atomic. | 4386 // case, then normal loads are atomic. |
4401 if (!Intrinsics::isMemoryOrderValid( | 4387 if (!Intrinsics::isMemoryOrderValid( |
4402 ID, getConstantMemoryOrder(Instr->getArg(2)))) { | 4388 ID, getConstantMemoryOrder(Instr->getArg(2)))) { |
4403 Func->setError("Unexpected memory ordering for AtomicStore"); | 4389 Func->setError("Unexpected memory ordering for AtomicStore"); |
4404 return; | 4390 return; |
4405 } | 4391 } |
(...skipping 25 matching lines...) Expand all Loading... |
4431 auto *Retry = InstARM32Label::create(Func, this); | 4417 auto *Retry = InstARM32Label::create(Func, this); |
4432 Variable64On32 *NewReg = makeI64RegPair(); | 4418 Variable64On32 *NewReg = makeI64RegPair(); |
4433 ValueVar->initHiLo(Func); | 4419 ValueVar->initHiLo(Func); |
4434 ValueVar->mustNotHaveReg(); | 4420 ValueVar->mustNotHaveReg(); |
4435 | 4421 |
4436 _dmb(); | 4422 _dmb(); |
4437 lowerAssign(InstAssign::create(Func, ValueVar, Value)); | 4423 lowerAssign(InstAssign::create(Func, ValueVar, Value)); |
4438 lowerAssign(InstAssign::create(Func, AddrVar, Addr)); | 4424 lowerAssign(InstAssign::create(Func, AddrVar, Addr)); |
4439 | 4425 |
4440 Context.insert(Retry); | 4426 Context.insert(Retry); |
4441 Context.insert(InstFakeDef::create(Func, NewReg)); | 4427 Context.insert<InstFakeDef>(NewReg); |
4442 lowerAssign(InstAssign::create(Func, NewReg, ValueVar)); | 4428 lowerAssign(InstAssign::create(Func, NewReg, ValueVar)); |
4443 Mem = formMemoryOperand(AddrVar, IceType_i64); | 4429 Mem = formMemoryOperand(AddrVar, IceType_i64); |
4444 _ldrex(Tmp, Mem); | 4430 _ldrex(Tmp, Mem); |
4445 // This fake-use both prevents the ldrex from being dead-code eliminated, | 4431 // This fake-use both prevents the ldrex from being dead-code eliminated, |
4446 // while also keeping liveness happy about all defs being used. | 4432 // while also keeping liveness happy about all defs being used. |
4447 Context.insert( | 4433 Context.insert<InstFakeUse>(Context.getLastInserted()->getDest()); |
4448 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | |
4449 _strex(Success, NewReg, Mem); | 4434 _strex(Success, NewReg, Mem); |
4450 _cmp(Success, _0); | 4435 _cmp(Success, _0); |
4451 _br(Retry, CondARM32::NE); | 4436 _br(Retry, CondARM32::NE); |
4452 | 4437 |
4453 Context.insert(InstFakeUse::create(Func, ValueVar->getLo())); | 4438 Context.insert<InstFakeUse>(ValueVar->getLo()); |
4454 Context.insert(InstFakeUse::create(Func, ValueVar->getHi())); | 4439 Context.insert<InstFakeUse>(ValueVar->getHi()); |
4455 Context.insert(InstFakeUse::create(Func, AddrVar)); | 4440 Context.insert<InstFakeUse>(AddrVar); |
4456 _dmb(); | 4441 _dmb(); |
4457 return; | 4442 return; |
4458 } | 4443 } |
4459 // non-64-bit stores are atomically as long as the address is aligned. This | 4444 // non-64-bit stores are atomically as long as the address is aligned. This |
4460 // is PNaCl, so addresses are aligned. | 4445 // is PNaCl, so addresses are aligned. |
4461 Variable *T = makeReg(ValueTy); | 4446 Variable *T = makeReg(ValueTy); |
4462 | 4447 |
4463 _dmb(); | 4448 _dmb(); |
4464 lowerAssign(InstAssign::create(Func, T, Value)); | 4449 lowerAssign(InstAssign::create(Func, T, Value)); |
4465 _str(T, formMemoryOperand(Addr, ValueTy)); | 4450 _str(T, formMemoryOperand(Addr, ValueTy)); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4543 } else { | 4528 } else { |
4544 TmpReg = makeReg(DestTy); | 4529 TmpReg = makeReg(DestTy); |
4545 New = Func->makeVariable(DestTy); | 4530 New = Func->makeVariable(DestTy); |
4546 NewReg = makeReg(DestTy); | 4531 NewReg = makeReg(DestTy); |
4547 Expected = Func->makeVariable(DestTy); | 4532 Expected = Func->makeVariable(DestTy); |
4548 ExpectedReg = makeReg(DestTy); | 4533 ExpectedReg = makeReg(DestTy); |
4549 } | 4534 } |
4550 | 4535 |
4551 Mem = formMemoryOperand(Instr->getArg(0), DestTy); | 4536 Mem = formMemoryOperand(Instr->getArg(0), DestTy); |
4552 if (DestTy == IceType_i64) { | 4537 if (DestTy == IceType_i64) { |
4553 Context.insert(InstFakeDef::create(Func, Expected)); | 4538 Context.insert<InstFakeDef>(Expected); |
4554 } | 4539 } |
4555 lowerAssign(InstAssign::create(Func, Expected, Instr->getArg(1))); | 4540 lowerAssign(InstAssign::create(Func, Expected, Instr->getArg(1))); |
4556 if (DestTy == IceType_i64) { | 4541 if (DestTy == IceType_i64) { |
4557 Context.insert(InstFakeDef::create(Func, New)); | 4542 Context.insert<InstFakeDef>(New); |
4558 } | 4543 } |
4559 lowerAssign(InstAssign::create(Func, New, Instr->getArg(2))); | 4544 lowerAssign(InstAssign::create(Func, New, Instr->getArg(2))); |
4560 _dmb(); | 4545 _dmb(); |
4561 | 4546 |
4562 Context.insert(Retry); | 4547 Context.insert(Retry); |
4563 if (DestTy == IceType_i64) { | 4548 if (DestTy == IceType_i64) { |
4564 Context.insert(InstFakeDef::create(Func, ExpectedReg, Expected)); | 4549 Context.insert<InstFakeDef>(ExpectedReg, Expected); |
4565 } | 4550 } |
4566 lowerAssign(InstAssign::create(Func, ExpectedReg, Expected)); | 4551 lowerAssign(InstAssign::create(Func, ExpectedReg, Expected)); |
4567 if (DestTy == IceType_i64) { | 4552 if (DestTy == IceType_i64) { |
4568 Context.insert(InstFakeDef::create(Func, NewReg, New)); | 4553 Context.insert<InstFakeDef>(NewReg, New); |
4569 } | 4554 } |
4570 lowerAssign(InstAssign::create(Func, NewReg, New)); | 4555 lowerAssign(InstAssign::create(Func, NewReg, New)); |
4571 | 4556 |
4572 _ldrex(TmpReg, Mem); | 4557 _ldrex(TmpReg, Mem); |
4573 Context.insert( | 4558 Context.insert<InstFakeUse>(Context.getLastInserted()->getDest()); |
4574 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | |
4575 if (DestTy == IceType_i64) { | 4559 if (DestTy == IceType_i64) { |
4576 auto *TmpReg64 = llvm::cast<Variable64On32>(TmpReg); | 4560 auto *TmpReg64 = llvm::cast<Variable64On32>(TmpReg); |
4577 auto *ExpectedReg64 = llvm::cast<Variable64On32>(ExpectedReg); | 4561 auto *ExpectedReg64 = llvm::cast<Variable64On32>(ExpectedReg); |
4578 // lowerAssign above has added fake-defs for TmpReg and ExpectedReg. Let's | 4562 // lowerAssign above has added fake-defs for TmpReg and ExpectedReg. Let's |
4579 // keep liveness happy, shall we? | 4563 // keep liveness happy, shall we? |
4580 Context.insert(InstFakeUse::create(Func, TmpReg)); | 4564 Context.insert<InstFakeUse>(TmpReg); |
4581 Context.insert(InstFakeUse::create(Func, ExpectedReg)); | 4565 Context.insert<InstFakeUse>(ExpectedReg); |
4582 _cmp(TmpReg64->getHi(), ExpectedReg64->getHi()); | 4566 _cmp(TmpReg64->getHi(), ExpectedReg64->getHi()); |
4583 _cmp(TmpReg64->getLo(), ExpectedReg64->getLo(), CondARM32::EQ); | 4567 _cmp(TmpReg64->getLo(), ExpectedReg64->getLo(), CondARM32::EQ); |
4584 } else { | 4568 } else { |
4585 _cmp(TmpReg, ExpectedReg); | 4569 _cmp(TmpReg, ExpectedReg); |
4586 } | 4570 } |
4587 _strex(Success, NewReg, Mem, CondARM32::EQ); | 4571 _strex(Success, NewReg, Mem, CondARM32::EQ); |
4588 if (DestTy == IceType_i64) { | 4572 if (DestTy == IceType_i64) { |
4589 auto *TmpReg64 = llvm::cast<Variable64On32>(TmpReg); | 4573 auto *TmpReg64 = llvm::cast<Variable64On32>(TmpReg); |
4590 auto *Expected64 = llvm::cast<Variable64On32>(Expected); | 4574 auto *Expected64 = llvm::cast<Variable64On32>(Expected); |
4591 _mov_redefined(Expected64->getHi(), TmpReg64->getHi(), CondARM32::NE); | 4575 _mov_redefined(Expected64->getHi(), TmpReg64->getHi(), CondARM32::NE); |
4592 _mov_redefined(Expected64->getLo(), TmpReg64->getLo(), CondARM32::NE); | 4576 _mov_redefined(Expected64->getLo(), TmpReg64->getLo(), CondARM32::NE); |
4593 auto *FakeDef = InstFakeDef::create(Func, Expected, TmpReg); | 4577 Context.insert<InstFakeDef>(Expected, TmpReg); |
4594 Context.insert(FakeDef); | 4578 _set_dest_redefined(); |
4595 FakeDef->setDestRedefined(); | |
4596 } else { | 4579 } else { |
4597 _mov_redefined(Expected, TmpReg, CondARM32::NE); | 4580 _mov_redefined(Expected, TmpReg, CondARM32::NE); |
4598 } | 4581 } |
4599 _cmp(Success, _0, CondARM32::EQ); | 4582 _cmp(Success, _0, CondARM32::EQ); |
4600 _br(Retry, CondARM32::NE); | 4583 _br(Retry, CondARM32::NE); |
4601 _dmb(); | 4584 _dmb(); |
4602 lowerAssign(InstAssign::create(Func, Dest, Expected)); | 4585 lowerAssign(InstAssign::create(Func, Dest, Expected)); |
4603 Context.insert(InstFakeUse::create(Func, Expected)); | 4586 Context.insert<InstFakeUse>(Expected); |
4604 if (auto *New64 = llvm::dyn_cast<Variable64On32>(New)) { | 4587 if (auto *New64 = llvm::dyn_cast<Variable64On32>(New)) { |
4605 Context.insert(InstFakeUse::create(Func, New64->getLo())); | 4588 Context.insert<InstFakeUse>(New64->getLo()); |
4606 Context.insert(InstFakeUse::create(Func, New64->getHi())); | 4589 Context.insert<InstFakeUse>(New64->getHi()); |
4607 } else { | 4590 } else { |
4608 Context.insert(InstFakeUse::create(Func, New)); | 4591 Context.insert<InstFakeUse>(New); |
4609 } | 4592 } |
4610 return; | 4593 return; |
4611 } | 4594 } |
4612 case Intrinsics::AtomicRMW: { | 4595 case Intrinsics::AtomicRMW: { |
4613 if (!Intrinsics::isMemoryOrderValid( | 4596 if (!Intrinsics::isMemoryOrderValid( |
4614 ID, getConstantMemoryOrder(Instr->getArg(3)))) { | 4597 ID, getConstantMemoryOrder(Instr->getArg(3)))) { |
4615 Func->setError("Unexpected memory ordering for AtomicRMW"); | 4598 Func->setError("Unexpected memory ordering for AtomicRMW"); |
4616 return; | 4599 return; |
4617 } | 4600 } |
4618 lowerAtomicRMW( | 4601 lowerAtomicRMW( |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4690 ValLoR = T; | 4673 ValLoR = T; |
4691 } | 4674 } |
4692 lowerCLZ(Dest, ValLoR, ValHiR); | 4675 lowerCLZ(Dest, ValLoR, ValHiR); |
4693 return; | 4676 return; |
4694 } | 4677 } |
4695 case Intrinsics::Fabs: { | 4678 case Intrinsics::Fabs: { |
4696 Type DestTy = Dest->getType(); | 4679 Type DestTy = Dest->getType(); |
4697 Variable *T = makeReg(DestTy); | 4680 Variable *T = makeReg(DestTy); |
4698 if (isVectorType(DestTy)) { | 4681 if (isVectorType(DestTy)) { |
4699 // Add a fake def to keep liveness consistent in the meantime. | 4682 // Add a fake def to keep liveness consistent in the meantime. |
4700 Context.insert(InstFakeDef::create(Func, T)); | 4683 Context.insert<InstFakeDef>(T); |
4701 _mov(Dest, T); | 4684 _mov(Dest, T); |
4702 UnimplementedError(Func->getContext()->getFlags()); | 4685 UnimplementedError(Func->getContext()->getFlags()); |
4703 return; | 4686 return; |
4704 } | 4687 } |
4705 _vabs(T, legalizeToReg(Instr->getArg(0))); | 4688 _vabs(T, legalizeToReg(Instr->getArg(0))); |
4706 _mov(Dest, T); | 4689 _mov(Dest, T); |
4707 return; | 4690 return; |
4708 } | 4691 } |
4709 case Intrinsics::Longjmp: { | 4692 case Intrinsics::Longjmp: { |
4710 llvm::report_fatal_error("longjmp should have been prelowered."); | 4693 llvm::report_fatal_error("longjmp should have been prelowered."); |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5155 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] is not legal in ARM, so we have to | 5138 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] is not legal in ARM, so we have to |
5156 // legalize the addressing mode to [BaseReg, OffsetReg{, LSL Shamt}]. | 5139 // legalize the addressing mode to [BaseReg, OffsetReg{, LSL Shamt}]. |
5157 // Instead of a zeroed BaseReg, we initialize it with OffsetImm: | 5140 // Instead of a zeroed BaseReg, we initialize it with OffsetImm: |
5158 // | 5141 // |
5159 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] -> | 5142 // [OffsetReg{, LSL Shamt}{, #OffsetImm}] -> |
5160 // mov BaseReg, #OffsetImm | 5143 // mov BaseReg, #OffsetImm |
5161 // use of [BaseReg, OffsetReg{, LSL Shamt}] | 5144 // use of [BaseReg, OffsetReg{, LSL Shamt}] |
5162 // | 5145 // |
5163 const Type PointerType = getPointerType(); | 5146 const Type PointerType = getPointerType(); |
5164 BaseVar = makeReg(PointerType); | 5147 BaseVar = makeReg(PointerType); |
5165 Context.insert( | 5148 Context.insert<InstAssign>(BaseVar, Ctx->getConstantInt32(OffsetImm)); |
5166 InstAssign::create(Func, BaseVar, Ctx->getConstantInt32(OffsetImm))); | |
5167 OffsetImm = 0; | 5149 OffsetImm = 0; |
5168 } else if (OffsetImm != 0) { | 5150 } else if (OffsetImm != 0) { |
5169 // ARM Ldr/Str instructions have limited range immediates. The formation | 5151 // ARM Ldr/Str instructions have limited range immediates. The formation |
5170 // loop above materialized an Immediate carelessly, so we ensure the | 5152 // loop above materialized an Immediate carelessly, so we ensure the |
5171 // generated offset is sane. | 5153 // generated offset is sane. |
5172 const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm; | 5154 const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm; |
5173 const InstArithmetic::OpKind Op = | 5155 const InstArithmetic::OpKind Op = |
5174 OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub; | 5156 OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub; |
5175 | 5157 |
5176 if (!CanHaveImm || !isLegalMemOffset(Ty, OffsetImm) || | 5158 if (!CanHaveImm || !isLegalMemOffset(Ty, OffsetImm) || |
(...skipping 10 matching lines...) Expand all Loading... |
5187 // here and don't form any address mode. | 5169 // here and don't form any address mode. |
5188 return nullptr; | 5170 return nullptr; |
5189 } | 5171 } |
5190 // We formed [Base, Offset {, LSL Amnt}, #const]. Oops. Legalize it to | 5172 // We formed [Base, Offset {, LSL Amnt}, #const]. Oops. Legalize it to |
5191 // | 5173 // |
5192 // [Base, Offset, {LSL amount}, #const] -> | 5174 // [Base, Offset, {LSL amount}, #const] -> |
5193 // add T, Base, #const | 5175 // add T, Base, #const |
5194 // use of [T, Offset {, LSL amount}] | 5176 // use of [T, Offset {, LSL amount}] |
5195 const Type PointerType = getPointerType(); | 5177 const Type PointerType = getPointerType(); |
5196 Variable *T = makeReg(PointerType); | 5178 Variable *T = makeReg(PointerType); |
5197 Context.insert(InstArithmetic::create( | 5179 Context.insert<InstArithmetic>(Op, T, BaseVar, |
5198 Func, Op, T, BaseVar, Ctx->getConstantInt32(PositiveOffset))); | 5180 Ctx->getConstantInt32(PositiveOffset)); |
5199 BaseVar = T; | 5181 BaseVar = T; |
5200 OffsetImm = 0; | 5182 OffsetImm = 0; |
5201 } | 5183 } |
5202 } | 5184 } |
5203 | 5185 |
5204 assert(BaseVar != nullptr); | 5186 assert(BaseVar != nullptr); |
5205 assert(OffsetImm == 0 || OffsetReg == nullptr); | 5187 assert(OffsetImm == 0 || OffsetReg == nullptr); |
5206 assert(OffsetReg == nullptr || CanHaveIndex); | 5188 assert(OffsetReg == nullptr || CanHaveIndex); |
5207 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm | 5189 assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm |
5208 : (ValidImmMask & OffsetImm) == OffsetImm); | 5190 : (ValidImmMask & OffsetImm) == OffsetImm); |
5209 | 5191 |
5210 if (OffsetReg != nullptr) { | 5192 if (OffsetReg != nullptr) { |
5211 Variable *OffsetR = makeReg(getPointerType()); | 5193 Variable *OffsetR = makeReg(getPointerType()); |
5212 Context.insert(InstAssign::create(Func, OffsetR, OffsetReg)); | 5194 Context.insert<InstAssign>(OffsetR, OffsetReg); |
5213 return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetR, ShiftKind, | 5195 return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetR, ShiftKind, |
5214 OffsetRegShamt); | 5196 OffsetRegShamt); |
5215 } | 5197 } |
5216 | 5198 |
5217 return OperandARM32Mem::create( | 5199 return OperandARM32Mem::create( |
5218 Func, Ty, BaseVar, | 5200 Func, Ty, BaseVar, |
5219 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm))); | 5201 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm))); |
5220 } | 5202 } |
5221 | 5203 |
5222 void TargetARM32::doAddressOptLoad() { | 5204 void TargetARM32::doAddressOptLoad() { |
5223 Inst *Instr = Context.getCur(); | 5205 Inst *Instr = Context.getCur(); |
5224 assert(llvm::isa<InstLoad>(Instr)); | 5206 assert(llvm::isa<InstLoad>(Instr)); |
5225 Variable *Dest = Instr->getDest(); | 5207 Variable *Dest = Instr->getDest(); |
5226 Operand *Addr = Instr->getSrc(0); | 5208 Operand *Addr = Instr->getSrc(0); |
5227 if (OperandARM32Mem *Mem = | 5209 if (OperandARM32Mem *Mem = |
5228 formAddressingMode(Dest->getType(), Func, Instr, Addr)) { | 5210 formAddressingMode(Dest->getType(), Func, Instr, Addr)) { |
5229 Instr->setDeleted(); | 5211 Instr->setDeleted(); |
5230 Context.insert(InstLoad::create(Func, Dest, Mem)); | 5212 Context.insert<InstLoad>(Dest, Mem); |
5231 } | 5213 } |
5232 } | 5214 } |
5233 | 5215 |
5234 void TargetARM32::randomlyInsertNop(float Probability, | 5216 void TargetARM32::randomlyInsertNop(float Probability, |
5235 RandomNumberGenerator &RNG) { | 5217 RandomNumberGenerator &RNG) { |
5236 RandomNumberGeneratorWrapper RNGW(RNG); | 5218 RandomNumberGeneratorWrapper RNGW(RNG); |
5237 if (RNGW.getTrueWithProbability(Probability)) { | 5219 if (RNGW.getTrueWithProbability(Probability)) { |
5238 UnimplementedError(Func->getContext()->getFlags()); | 5220 UnimplementedError(Func->getContext()->getFlags()); |
5239 } | 5221 } |
5240 } | 5222 } |
5241 | 5223 |
5242 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { | 5224 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
5243 Func->setError("Phi found in regular instruction list"); | 5225 Func->setError("Phi found in regular instruction list"); |
5244 } | 5226 } |
5245 | 5227 |
5246 void TargetARM32::lowerRet(const InstRet *Inst) { | 5228 void TargetARM32::lowerRet(const InstRet *Inst) { |
5247 Variable *Reg = nullptr; | 5229 Variable *Reg = nullptr; |
5248 if (Inst->hasRetValue()) { | 5230 if (Inst->hasRetValue()) { |
5249 Operand *Src0 = Inst->getRetValue(); | 5231 Operand *Src0 = Inst->getRetValue(); |
5250 Type Ty = Src0->getType(); | 5232 Type Ty = Src0->getType(); |
5251 if (Ty == IceType_i64) { | 5233 if (Ty == IceType_i64) { |
5252 Src0 = legalizeUndef(Src0); | 5234 Src0 = legalizeUndef(Src0); |
5253 Variable *R0 = legalizeToReg(loOperand(Src0), RegARM32::Reg_r0); | 5235 Variable *R0 = legalizeToReg(loOperand(Src0), RegARM32::Reg_r0); |
5254 Variable *R1 = legalizeToReg(hiOperand(Src0), RegARM32::Reg_r1); | 5236 Variable *R1 = legalizeToReg(hiOperand(Src0), RegARM32::Reg_r1); |
5255 Reg = R0; | 5237 Reg = R0; |
5256 Context.insert(InstFakeUse::create(Func, R1)); | 5238 Context.insert<InstFakeUse>(R1); |
5257 } else if (Ty == IceType_f32) { | 5239 } else if (Ty == IceType_f32) { |
5258 Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0); | 5240 Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0); |
5259 Reg = S0; | 5241 Reg = S0; |
5260 } else if (Ty == IceType_f64) { | 5242 } else if (Ty == IceType_f64) { |
5261 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); | 5243 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); |
5262 Reg = D0; | 5244 Reg = D0; |
5263 } else if (isVectorType(Src0->getType())) { | 5245 } else if (isVectorType(Src0->getType())) { |
5264 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); | 5246 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); |
5265 Reg = Q0; | 5247 Reg = Q0; |
5266 } else { | 5248 } else { |
5267 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 5249 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
5268 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); | 5250 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); |
5269 _mov(Reg, Src0F, CondARM32::AL); | 5251 _mov(Reg, Src0F, CondARM32::AL); |
5270 } | 5252 } |
5271 } | 5253 } |
5272 // Add a ret instruction even if sandboxing is enabled, because addEpilog | 5254 // Add a ret instruction even if sandboxing is enabled, because addEpilog |
5273 // explicitly looks for a ret instruction as a marker for where to insert the | 5255 // explicitly looks for a ret instruction as a marker for where to insert the |
5274 // frame removal instructions. addEpilog is responsible for restoring the | 5256 // frame removal instructions. addEpilog is responsible for restoring the |
5275 // "lr" register as needed prior to this ret instruction. | 5257 // "lr" register as needed prior to this ret instruction. |
5276 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 5258 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
5277 | 5259 |
5278 // Add a fake use of sp to make sure sp stays alive for the entire function. | 5260 // Add a fake use of sp to make sure sp stays alive for the entire function. |
5279 // Otherwise post-call sp adjustments get dead-code eliminated. | 5261 // Otherwise post-call sp adjustments get dead-code eliminated. |
5280 // TODO: Are there more places where the fake use should be inserted? E.g. | 5262 // TODO: Are there more places where the fake use should be inserted? E.g. |
5281 // "void f(int n){while(1) g(n);}" may not have a ret instruction. | 5263 // "void f(int n){while(1) g(n);}" may not have a ret instruction. |
5282 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 5264 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
5283 Context.insert(InstFakeUse::create(Func, SP)); | 5265 Context.insert<InstFakeUse>(SP); |
5284 } | 5266 } |
5285 | 5267 |
5286 void TargetARM32::lowerSelect(const InstSelect *Inst) { | 5268 void TargetARM32::lowerSelect(const InstSelect *Inst) { |
5287 Variable *Dest = Inst->getDest(); | 5269 Variable *Dest = Inst->getDest(); |
5288 Type DestTy = Dest->getType(); | 5270 Type DestTy = Dest->getType(); |
5289 Operand *SrcT = Inst->getTrueOperand(); | 5271 Operand *SrcT = Inst->getTrueOperand(); |
5290 Operand *SrcF = Inst->getFalseOperand(); | 5272 Operand *SrcF = Inst->getFalseOperand(); |
5291 Operand *Condition = Inst->getCondition(); | 5273 Operand *Condition = Inst->getCondition(); |
5292 | 5274 |
5293 if (isVectorType(DestTy)) { | 5275 if (isVectorType(DestTy)) { |
5294 Variable *T = makeReg(DestTy); | 5276 Variable *T = makeReg(DestTy); |
5295 Context.insert(InstFakeDef::create(Func, T)); | 5277 Context.insert<InstFakeDef>(T); |
5296 _mov(Dest, T); | 5278 _mov(Dest, T); |
5297 UnimplementedError(Func->getContext()->getFlags()); | 5279 UnimplementedError(Func->getContext()->getFlags()); |
5298 return; | 5280 return; |
5299 } | 5281 } |
5300 | 5282 |
5301 lowerInt1ForSelect(Dest, Condition, legalizeUndef(SrcT), legalizeUndef(SrcF)); | 5283 lowerInt1ForSelect(Dest, Condition, legalizeUndef(SrcT), legalizeUndef(SrcF)); |
5302 } | 5284 } |
5303 | 5285 |
5304 void TargetARM32::lowerStore(const InstStore *Inst) { | 5286 void TargetARM32::lowerStore(const InstStore *Inst) { |
5305 Operand *Value = Inst->getData(); | 5287 Operand *Value = Inst->getData(); |
(...skipping 14 matching lines...) Expand all Loading... |
5320 } | 5302 } |
5321 | 5303 |
5322 void TargetARM32::doAddressOptStore() { | 5304 void TargetARM32::doAddressOptStore() { |
5323 Inst *Instr = Context.getCur(); | 5305 Inst *Instr = Context.getCur(); |
5324 assert(llvm::isa<InstStore>(Instr)); | 5306 assert(llvm::isa<InstStore>(Instr)); |
5325 Operand *Src = Instr->getSrc(0); | 5307 Operand *Src = Instr->getSrc(0); |
5326 Operand *Addr = Instr->getSrc(1); | 5308 Operand *Addr = Instr->getSrc(1); |
5327 if (OperandARM32Mem *Mem = | 5309 if (OperandARM32Mem *Mem = |
5328 formAddressingMode(Src->getType(), Func, Instr, Addr)) { | 5310 formAddressingMode(Src->getType(), Func, Instr, Addr)) { |
5329 Instr->setDeleted(); | 5311 Instr->setDeleted(); |
5330 Context.insert(InstStore::create(Func, Src, Mem)); | 5312 Context.insert<InstStore>(Src, Mem); |
5331 } | 5313 } |
5332 } | 5314 } |
5333 | 5315 |
5334 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 5316 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
5335 // This implements the most naive possible lowering. | 5317 // This implements the most naive possible lowering. |
5336 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default | 5318 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default |
5337 Operand *Src0 = Inst->getComparison(); | 5319 Operand *Src0 = Inst->getComparison(); |
5338 SizeT NumCases = Inst->getNumCases(); | 5320 SizeT NumCases = Inst->getNumCases(); |
5339 if (Src0->getType() == IceType_i64) { | 5321 if (Src0->getType() == IceType_i64) { |
5340 Src0 = legalizeUndef(Src0); | 5322 Src0 = legalizeUndef(Src0); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5378 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 5360 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
5379 _trap(); | 5361 _trap(); |
5380 } | 5362 } |
5381 | 5363 |
5382 void TargetARM32::prelowerPhis() { | 5364 void TargetARM32::prelowerPhis() { |
5383 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); | 5365 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); |
5384 } | 5366 } |
5385 | 5367 |
5386 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { | 5368 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { |
5387 Variable *Reg = makeReg(Ty, RegNum); | 5369 Variable *Reg = makeReg(Ty, RegNum); |
5388 Context.insert(InstFakeDef::create(Func, Reg)); | 5370 Context.insert<InstFakeDef>(Reg); |
5389 UnimplementedError(Func->getContext()->getFlags()); | 5371 UnimplementedError(Func->getContext()->getFlags()); |
5390 return Reg; | 5372 return Reg; |
5391 } | 5373 } |
5392 | 5374 |
5393 // Helper for legalize() to emit the right code to lower an operand to a | 5375 // Helper for legalize() to emit the right code to lower an operand to a |
5394 // register of the appropriate type. | 5376 // register of the appropriate type. |
5395 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 5377 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
5396 Type Ty = Src->getType(); | 5378 Type Ty = Src->getType(); |
5397 Variable *Reg = makeReg(Ty, RegNum); | 5379 Variable *Reg = makeReg(Ty, RegNum); |
5398 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { | 5380 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5552 Variable *T = makeReg(Ty, RegNum); | 5534 Variable *T = makeReg(Ty, RegNum); |
5553 _mov(T, | 5535 _mov(T, |
5554 OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm)); | 5536 OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm)); |
5555 return T; | 5537 return T; |
5556 } | 5538 } |
5557 | 5539 |
5558 if (Ty == IceType_f64 && isFloatingPointZero(From)) { | 5540 if (Ty == IceType_f64 && isFloatingPointZero(From)) { |
5559 // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32 | 5541 // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32 |
5560 // because ARM does not have a veor instruction with S registers. | 5542 // because ARM does not have a veor instruction with S registers. |
5561 Variable *T = makeReg(IceType_f64, RegNum); | 5543 Variable *T = makeReg(IceType_f64, RegNum); |
5562 Context.insert(InstFakeDef::create(Func, T)); | 5544 Context.insert<InstFakeDef>(T); |
5563 _veor(T, T, T); | 5545 _veor(T, T, T); |
5564 return T; | 5546 return T; |
5565 } | 5547 } |
5566 | 5548 |
5567 // Load floats/doubles from literal pool. | 5549 // Load floats/doubles from literal pool. |
5568 std::string Buffer; | 5550 std::string Buffer; |
5569 llvm::raw_string_ostream StrBuf(Buffer); | 5551 llvm::raw_string_ostream StrBuf(Buffer); |
5570 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); | 5552 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); |
5571 llvm::cast<Constant>(From)->setShouldBePooled(true); | 5553 llvm::cast<Constant>(From)->setShouldBePooled(true); |
5572 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); | 5554 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6180 } | 6162 } |
6181 | 6163 |
6182 InstARM32Call *TargetARM32::Sandboxer::bl(Variable *ReturnReg, | 6164 InstARM32Call *TargetARM32::Sandboxer::bl(Variable *ReturnReg, |
6183 Operand *CallTarget) { | 6165 Operand *CallTarget) { |
6184 if (Target->NeedSandboxing) { | 6166 if (Target->NeedSandboxing) { |
6185 if (auto *CallTargetR = llvm::dyn_cast<Variable>(CallTarget)) { | 6167 if (auto *CallTargetR = llvm::dyn_cast<Variable>(CallTarget)) { |
6186 Target->_bic(CallTargetR, CallTargetR, | 6168 Target->_bic(CallTargetR, CallTargetR, |
6187 indirectBranchBicMask(Target->Func)); | 6169 indirectBranchBicMask(Target->Func)); |
6188 } | 6170 } |
6189 } | 6171 } |
6190 auto *Call = InstARM32Call::create(Target->Func, ReturnReg, CallTarget); | 6172 return Target->Context.insert<InstARM32Call>(ReturnReg, CallTarget); |
6191 Target->Context.insert(Call); | |
6192 return Call; | |
6193 } | 6173 } |
6194 | 6174 |
6195 void TargetARM32::Sandboxer::ldr(Variable *Dest, OperandARM32Mem *Mem, | 6175 void TargetARM32::Sandboxer::ldr(Variable *Dest, OperandARM32Mem *Mem, |
6196 CondARM32::Cond Pred) { | 6176 CondARM32::Cond Pred) { |
6197 Variable *MemBase = Mem->getBase(); | 6177 Variable *MemBase = Mem->getBase(); |
6198 if (Target->NeedSandboxing && baseNeedsBic(MemBase)) { | 6178 if (Target->NeedSandboxing && baseNeedsBic(MemBase)) { |
6199 assert(!Mem->isRegReg()); | 6179 assert(!Mem->isRegReg()); |
6200 Target->_bic(MemBase, MemBase, memOpBicMask(Target->Func), Pred); | 6180 Target->_bic(MemBase, MemBase, memOpBicMask(Target->Func), Pred); |
6201 } | 6181 } |
6202 Target->_ldr(Dest, Mem, Pred); | 6182 Target->_ldr(Dest, Mem, Pred); |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6443 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 6423 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
6444 // However, for compatibility with current NaCl LLVM, don't claim that. | 6424 // However, for compatibility with current NaCl LLVM, don't claim that. |
6445 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6425 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
6446 } | 6426 } |
6447 | 6427 |
6448 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 6428 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
6449 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6429 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
6450 llvm::SmallBitVector TargetARM32::ScratchRegs; | 6430 llvm::SmallBitVector TargetARM32::ScratchRegs; |
6451 | 6431 |
6452 } // end of namespace Ice | 6432 } // end of namespace Ice |
OLD | NEW |