Chromium Code Reviews| 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 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 return; | 461 return; |
| 462 } | 462 } |
| 463 } | 463 } |
| 464 switch (DestTy) { | 464 switch (DestTy) { |
| 465 default: | 465 default: |
| 466 return; | 466 return; |
| 467 case IceType_i64: { | 467 case IceType_i64: { |
| 468 // Technically, ARM has its own aeabi routines, but we can use the | 468 // Technically, ARM has its own aeabi routines, but we can use the |
| 469 // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses | 469 // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses |
| 470 // the more standard __moddi3 for rem. | 470 // the more standard __moddi3 for rem. |
| 471 Operand *TargetHelper = nullptr; | 471 RuntimeHelperFuncKind HelperName = H_Num; |
|
Jim Stichnoth
2016/03/10 00:24:46
Nit: it's more of a HelperID than a HelperName.
Karl
2016/03/16 22:50:52
Changed to HelperID.
| |
| 472 switch (Op) { | 472 switch (Op) { |
| 473 default: | 473 default: |
| 474 return; | 474 return; |
| 475 case InstArithmetic::Udiv: | 475 case InstArithmetic::Udiv: |
| 476 TargetHelper = Ctx->getConstantExternSym(H_udiv_i64); | 476 HelperName = H_udiv_i64; |
| 477 break; | 477 break; |
| 478 case InstArithmetic::Sdiv: | 478 case InstArithmetic::Sdiv: |
| 479 TargetHelper = Ctx->getConstantExternSym(H_sdiv_i64); | 479 HelperName = H_sdiv_i64; |
| 480 break; | 480 break; |
| 481 case InstArithmetic::Urem: | 481 case InstArithmetic::Urem: |
| 482 TargetHelper = Ctx->getConstantExternSym(H_urem_i64); | 482 HelperName = H_urem_i64; |
| 483 break; | 483 break; |
| 484 case InstArithmetic::Srem: | 484 case InstArithmetic::Srem: |
| 485 TargetHelper = Ctx->getConstantExternSym(H_srem_i64); | 485 HelperName = H_srem_i64; |
| 486 break; | 486 break; |
| 487 } | 487 } |
| 488 assert(TargetHelper != nullptr); | 488 Operand *TargetHelper = getRuntimeHelperFunc(HelperName); |
| 489 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; | 489 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; |
| 490 constexpr SizeT MaxArgs = 2; | 490 constexpr SizeT MaxArgs = 2; |
| 491 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 491 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 492 NoTailCall, IsTargetHelperCall); | 492 NoTailCall, IsTargetHelperCall); |
| 493 Call->addArg(Instr->getSrc(0)); | 493 Call->addArg(Instr->getSrc(0)); |
| 494 Call->addArg(Instr->getSrc(1)); | 494 Call->addArg(Instr->getSrc(1)); |
| 495 Instr->setDeleted(); | 495 Instr->setDeleted(); |
| 496 return; | 496 return; |
| 497 } | 497 } |
| 498 case IceType_i32: | 498 case IceType_i32: |
| 499 case IceType_i16: | 499 case IceType_i16: |
| 500 case IceType_i8: { | 500 case IceType_i8: { |
| 501 const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm); | 501 const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm); |
| 502 InstCast::OpKind CastKind; | 502 InstCast::OpKind CastKind; |
| 503 Operand *TargetHelper; | 503 RuntimeHelperFuncKind HelperName = H_Num; |
| 504 switch (Op) { | 504 switch (Op) { |
| 505 default: | 505 default: |
| 506 return; | 506 return; |
| 507 case InstArithmetic::Udiv: | 507 case InstArithmetic::Udiv: |
| 508 TargetHelper = | 508 HelperName = HasHWDiv ? H_Num : H_udiv_i32; |
| 509 HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_udiv_i32); | |
| 510 CastKind = InstCast::Zext; | 509 CastKind = InstCast::Zext; |
| 511 break; | 510 break; |
| 512 case InstArithmetic::Sdiv: | 511 case InstArithmetic::Sdiv: |
| 513 TargetHelper = | 512 HelperName = HasHWDiv ? H_Num : H_sdiv_i32; |
| 514 HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_sdiv_i32); | |
| 515 CastKind = InstCast::Sext; | 513 CastKind = InstCast::Sext; |
| 516 break; | 514 break; |
| 517 case InstArithmetic::Urem: | 515 case InstArithmetic::Urem: |
| 518 TargetHelper = | 516 HelperName = HasHWDiv ? H_Num : H_urem_i32; |
| 519 HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_urem_i32); | |
| 520 CastKind = InstCast::Zext; | 517 CastKind = InstCast::Zext; |
| 521 break; | 518 break; |
| 522 case InstArithmetic::Srem: | 519 case InstArithmetic::Srem: |
| 523 TargetHelper = | 520 HelperName = HasHWDiv ? H_Num : H_srem_i32; |
| 524 HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_srem_i32); | |
| 525 CastKind = InstCast::Sext; | 521 CastKind = InstCast::Sext; |
| 526 break; | 522 break; |
| 527 } | 523 } |
| 528 if (TargetHelper == nullptr) { | 524 if (HelperName == H_Num) { |
| 529 // TargetHelper should only ever be nullptr when the processor does not | 525 // HelperName should only ever be undefined when the processor does not |
| 530 // have a hardware divider. If any other helpers are ever introduced, | 526 // have a hardware divider. If any other helpers are ever introduced, |
| 531 // the following assert will have to be modified. | 527 // the following assert will have to be modified. |
| 532 assert(HasHWDiv); | 528 assert(HasHWDiv); |
| 533 return; | 529 return; |
| 534 } | 530 } |
| 535 Operand *Src0 = Instr->getSrc(0); | 531 Operand *Src0 = Instr->getSrc(0); |
| 536 Operand *Src1 = Instr->getSrc(1); | 532 Operand *Src1 = Instr->getSrc(1); |
| 537 if (DestTy != IceType_i32) { | 533 if (DestTy != IceType_i32) { |
| 538 // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0, | 534 // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0, |
| 539 // we just insert a InstCast right before the call to the helper. | 535 // we just insert a InstCast right before the call to the helper. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 553 } else { | 549 } else { |
| 554 NewC = (NewC << ShAmt) >> ShAmt; | 550 NewC = (NewC << ShAmt) >> ShAmt; |
| 555 } | 551 } |
| 556 Src1 = Ctx->getConstantInt32(NewC); | 552 Src1 = Ctx->getConstantInt32(NewC); |
| 557 } else { | 553 } else { |
| 558 Variable *Src1_32 = Func->makeVariable(IceType_i32); | 554 Variable *Src1_32 = Func->makeVariable(IceType_i32); |
| 559 Context.insert<InstCast>(CastKind, Src1_32, Src1); | 555 Context.insert<InstCast>(CastKind, Src1_32, Src1); |
| 560 Src1 = Src1_32; | 556 Src1 = Src1_32; |
| 561 } | 557 } |
| 562 } | 558 } |
| 563 assert(TargetHelper != nullptr); | 559 Operand *TargetHelper = getRuntimeHelperFunc(HelperName); |
| 564 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; | 560 ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem; |
| 565 constexpr SizeT MaxArgs = 2; | 561 constexpr SizeT MaxArgs = 2; |
| 566 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 562 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 567 NoTailCall, IsTargetHelperCall); | 563 NoTailCall, IsTargetHelperCall); |
| 568 assert(Src0->getType() == IceType_i32); | 564 assert(Src0->getType() == IceType_i32); |
| 569 Call->addArg(Src0); | 565 Call->addArg(Src0); |
| 570 assert(Src1->getType() == IceType_i32); | 566 assert(Src1->getType() == IceType_i32); |
| 571 Call->addArg(Src1); | 567 Call->addArg(Src1); |
| 572 Instr->setDeleted(); | 568 Instr->setDeleted(); |
| 573 return; | 569 return; |
| 574 } | 570 } |
| 575 case IceType_f64: | 571 case IceType_f64: |
| 576 case IceType_f32: { | 572 case IceType_f32: { |
| 577 if (Op != InstArithmetic::Frem) { | 573 if (Op != InstArithmetic::Frem) { |
| 578 return; | 574 return; |
| 579 } | 575 } |
| 580 constexpr SizeT MaxArgs = 2; | 576 constexpr SizeT MaxArgs = 2; |
| 581 Operand *TargetHelper = Ctx->getConstantExternSym( | 577 Operand *TargetHelper = |
| 582 DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64); | 578 getRuntimeHelperFunc(DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64); |
| 583 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 579 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 584 NoTailCall, IsTargetHelperCall); | 580 NoTailCall, IsTargetHelperCall); |
| 585 Call->addArg(Instr->getSrc(0)); | 581 Call->addArg(Instr->getSrc(0)); |
| 586 Call->addArg(Instr->getSrc(1)); | 582 Call->addArg(Instr->getSrc(1)); |
| 587 Instr->setDeleted(); | 583 Instr->setDeleted(); |
| 588 return; | 584 return; |
| 589 } | 585 } |
| 590 } | 586 } |
| 591 llvm::report_fatal_error("Control flow should never have reached here."); | 587 llvm::report_fatal_error("Control flow should never have reached here."); |
| 592 } | 588 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 612 switch (CastKind) { | 608 switch (CastKind) { |
| 613 default: | 609 default: |
| 614 return; | 610 return; |
| 615 case InstCast::Fptosi: | 611 case InstCast::Fptosi: |
| 616 case InstCast::Fptoui: { | 612 case InstCast::Fptoui: { |
| 617 if (DestTy != IceType_i64) { | 613 if (DestTy != IceType_i64) { |
| 618 return; | 614 return; |
| 619 } | 615 } |
| 620 const bool DestIsSigned = CastKind == InstCast::Fptosi; | 616 const bool DestIsSigned = CastKind == InstCast::Fptosi; |
| 621 const bool Src0IsF32 = isFloat32Asserting32Or64(SrcTy); | 617 const bool Src0IsF32 = isFloat32Asserting32Or64(SrcTy); |
| 622 Operand *TargetHelper = Ctx->getConstantExternSym( | 618 Operand *TargetHelper = getRuntimeHelperFunc( |
| 623 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64) | 619 Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64) |
| 624 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64)); | 620 : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64)); |
| 625 static constexpr SizeT MaxArgs = 1; | 621 static constexpr SizeT MaxArgs = 1; |
| 626 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 622 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 627 NoTailCall, IsTargetHelperCall); | 623 NoTailCall, IsTargetHelperCall); |
| 628 Call->addArg(Src0); | 624 Call->addArg(Src0); |
| 629 Instr->setDeleted(); | 625 Instr->setDeleted(); |
| 630 return; | 626 return; |
| 631 } | 627 } |
| 632 case InstCast::Sitofp: | 628 case InstCast::Sitofp: |
| 633 case InstCast::Uitofp: { | 629 case InstCast::Uitofp: { |
| 634 if (SrcTy != IceType_i64) { | 630 if (SrcTy != IceType_i64) { |
| 635 return; | 631 return; |
| 636 } | 632 } |
| 637 const bool SourceIsSigned = CastKind == InstCast::Sitofp; | 633 const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
| 638 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); | 634 const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); |
| 639 Operand *TargetHelper = Ctx->getConstantExternSym( | 635 Operand *TargetHelper = getRuntimeHelperFunc( |
| 640 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32) | 636 DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32) |
| 641 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64)); | 637 : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64)); |
| 642 static constexpr SizeT MaxArgs = 1; | 638 static constexpr SizeT MaxArgs = 1; |
| 643 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 639 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 644 NoTailCall, IsTargetHelperCall); | 640 NoTailCall, IsTargetHelperCall); |
| 645 Call->addArg(Src0); | 641 Call->addArg(Src0); |
| 646 Instr->setDeleted(); | 642 Instr->setDeleted(); |
| 647 return; | 643 return; |
| 648 } | 644 } |
| 649 case InstCast::Bitcast: { | 645 case InstCast::Bitcast: { |
| 650 if (DestTy == SrcTy) { | 646 if (DestTy == SrcTy) { |
| 651 return; | 647 return; |
| 652 } | 648 } |
| 653 Variable *CallDest = Dest; | 649 Variable *CallDest = Dest; |
| 654 const char *HelperName = nullptr; | 650 RuntimeHelperFuncKind HelperName = H_Num; |
| 655 switch (DestTy) { | 651 switch (DestTy) { |
| 656 default: | 652 default: |
| 657 return; | 653 return; |
| 658 case IceType_i8: | 654 case IceType_i8: |
| 659 assert(SrcTy == IceType_v8i1); | 655 assert(SrcTy == IceType_v8i1); |
| 660 HelperName = H_bitcast_8xi1_i8; | 656 HelperName = H_bitcast_8xi1_i8; |
| 661 CallDest = Func->makeVariable(IceType_i32); | 657 CallDest = Func->makeVariable(IceType_i32); |
| 662 break; | 658 break; |
| 663 case IceType_i16: | 659 case IceType_i16: |
| 664 assert(SrcTy == IceType_v16i1); | 660 assert(SrcTy == IceType_v16i1); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 675 } break; | 671 } break; |
| 676 case IceType_v16i1: { | 672 case IceType_v16i1: { |
| 677 assert(SrcTy == IceType_i16); | 673 assert(SrcTy == IceType_i16); |
| 678 HelperName = H_bitcast_i16_16xi1; | 674 HelperName = H_bitcast_i16_16xi1; |
| 679 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); | 675 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
| 680 // Arguments to functions are required to be at least 32 bits wide. | 676 // Arguments to functions are required to be at least 32 bits wide. |
| 681 Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0); | 677 Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0); |
| 682 Src0 = Src0AsI32; | 678 Src0 = Src0AsI32; |
| 683 } break; | 679 } break; |
| 684 } | 680 } |
| 685 assert(HelperName != nullptr); | |
| 686 constexpr SizeT MaxSrcs = 1; | 681 constexpr SizeT MaxSrcs = 1; |
| 687 InstCall *Call = makeHelperCall(HelperName, CallDest, MaxSrcs); | 682 InstCall *Call = makeHelperCall(HelperName, CallDest, MaxSrcs); |
| 688 Call->addArg(Src0); | 683 Call->addArg(Src0); |
| 689 Context.insert(Call); | 684 Context.insert(Call); |
| 690 // The PNaCl ABI disallows i8/i16 return types, so truncate the helper | 685 // The PNaCl ABI disallows i8/i16 return types, so truncate the helper |
| 691 // call result to the appropriate type as necessary. | 686 // call result to the appropriate type as necessary. |
| 692 if (CallDest->getType() != Dest->getType()) | 687 if (CallDest->getType() != Dest->getType()) |
| 693 Context.insert<InstCast>(InstCast::Trunc, Dest, CallDest); | 688 Context.insert<InstCast>(InstCast::Trunc, Dest, CallDest); |
| 694 Instr->setDeleted(); | 689 Instr->setDeleted(); |
| 695 return; | 690 return; |
| 696 } | 691 } |
| 697 } | 692 } |
| 698 llvm::report_fatal_error("Control flow should never have reached here."); | 693 llvm::report_fatal_error("Control flow should never have reached here."); |
| 699 } | 694 } |
| 700 case Inst::IntrinsicCall: { | 695 case Inst::IntrinsicCall: { |
| 701 Variable *Dest = Instr->getDest(); | 696 Variable *Dest = Instr->getDest(); |
| 702 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); | 697 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); |
| 703 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; | 698 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; |
| 704 switch (ID) { | 699 switch (ID) { |
| 705 default: | 700 default: |
| 706 return; | 701 return; |
| 707 case Intrinsics::Ctpop: { | 702 case Intrinsics::Ctpop: { |
| 708 Operand *Src0 = IntrinsicCall->getArg(0); | 703 Operand *Src0 = IntrinsicCall->getArg(0); |
| 709 Operand *TargetHelper = Ctx->getConstantExternSym( | 704 Operand *TargetHelper = getRuntimeHelperFunc( |
| 710 isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32 | 705 isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32 |
| 711 : H_call_ctpop_i64); | 706 : H_call_ctpop_i64); |
| 712 static constexpr SizeT MaxArgs = 1; | 707 static constexpr SizeT MaxArgs = 1; |
| 713 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 708 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 714 NoTailCall, IsTargetHelperCall); | 709 NoTailCall, IsTargetHelperCall); |
| 715 Call->addArg(Src0); | 710 Call->addArg(Src0); |
| 716 Instr->setDeleted(); | 711 Instr->setDeleted(); |
| 717 if (Src0->getType() == IceType_i64) { | 712 if (Src0->getType() == IceType_i64) { |
| 718 ARM32HelpersPostamble[TargetHelper] = &TargetARM32::postambleCtpop64; | 713 ARM32HelpersPostamble[TargetHelper] = &TargetARM32::postambleCtpop64; |
| 719 } | 714 } |
| 720 return; | 715 return; |
| 721 } | 716 } |
| 722 case Intrinsics::Longjmp: { | 717 case Intrinsics::Longjmp: { |
| 723 static constexpr SizeT MaxArgs = 2; | 718 static constexpr SizeT MaxArgs = 2; |
| 724 static constexpr Variable *NoDest = nullptr; | 719 static constexpr Variable *NoDest = nullptr; |
| 725 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_longjmp); | 720 Operand *TargetHelper = getRuntimeHelperFunc(H_call_longjmp); |
| 726 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, | 721 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
| 727 NoTailCall, IsTargetHelperCall); | 722 NoTailCall, IsTargetHelperCall); |
| 728 Call->addArg(IntrinsicCall->getArg(0)); | 723 Call->addArg(IntrinsicCall->getArg(0)); |
| 729 Call->addArg(IntrinsicCall->getArg(1)); | 724 Call->addArg(IntrinsicCall->getArg(1)); |
| 730 Instr->setDeleted(); | 725 Instr->setDeleted(); |
| 731 return; | 726 return; |
| 732 } | 727 } |
| 733 case Intrinsics::Memcpy: { | 728 case Intrinsics::Memcpy: { |
| 734 // In the future, we could potentially emit an inline memcpy/memset, etc. | 729 // In the future, we could potentially emit an inline memcpy/memset, etc. |
| 735 // for intrinsic calls w/ a known length. | 730 // for intrinsic calls w/ a known length. |
| 736 static constexpr SizeT MaxArgs = 3; | 731 static constexpr SizeT MaxArgs = 3; |
| 737 static constexpr Variable *NoDest = nullptr; | 732 static constexpr Variable *NoDest = nullptr; |
| 738 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memcpy); | 733 Operand *TargetHelper = getRuntimeHelperFunc(H_call_memcpy); |
| 739 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, | 734 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
| 740 NoTailCall, IsTargetHelperCall); | 735 NoTailCall, IsTargetHelperCall); |
| 741 Call->addArg(IntrinsicCall->getArg(0)); | 736 Call->addArg(IntrinsicCall->getArg(0)); |
| 742 Call->addArg(IntrinsicCall->getArg(1)); | 737 Call->addArg(IntrinsicCall->getArg(1)); |
| 743 Call->addArg(IntrinsicCall->getArg(2)); | 738 Call->addArg(IntrinsicCall->getArg(2)); |
| 744 Instr->setDeleted(); | 739 Instr->setDeleted(); |
| 745 return; | 740 return; |
| 746 } | 741 } |
| 747 case Intrinsics::Memmove: { | 742 case Intrinsics::Memmove: { |
| 748 static constexpr SizeT MaxArgs = 3; | 743 static constexpr SizeT MaxArgs = 3; |
| 749 static constexpr Variable *NoDest = nullptr; | 744 static constexpr Variable *NoDest = nullptr; |
| 750 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memmove); | 745 Operand *TargetHelper = getRuntimeHelperFunc(H_call_memmove); |
| 751 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, | 746 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
| 752 NoTailCall, IsTargetHelperCall); | 747 NoTailCall, IsTargetHelperCall); |
| 753 Call->addArg(IntrinsicCall->getArg(0)); | 748 Call->addArg(IntrinsicCall->getArg(0)); |
| 754 Call->addArg(IntrinsicCall->getArg(1)); | 749 Call->addArg(IntrinsicCall->getArg(1)); |
| 755 Call->addArg(IntrinsicCall->getArg(2)); | 750 Call->addArg(IntrinsicCall->getArg(2)); |
| 756 Instr->setDeleted(); | 751 Instr->setDeleted(); |
| 757 return; | 752 return; |
| 758 } | 753 } |
| 759 case Intrinsics::Memset: { | 754 case Intrinsics::Memset: { |
| 760 // The value operand needs to be extended to a stack slot size because the | 755 // The value operand needs to be extended to a stack slot size because the |
| 761 // PNaCl ABI requires arguments to be at least 32 bits wide. | 756 // PNaCl ABI requires arguments to be at least 32 bits wide. |
| 762 Operand *ValOp = IntrinsicCall->getArg(1); | 757 Operand *ValOp = IntrinsicCall->getArg(1); |
| 763 assert(ValOp->getType() == IceType_i8); | 758 assert(ValOp->getType() == IceType_i8); |
| 764 Variable *ValExt = Func->makeVariable(stackSlotType()); | 759 Variable *ValExt = Func->makeVariable(stackSlotType()); |
| 765 Context.insert<InstCast>(InstCast::Zext, ValExt, ValOp); | 760 Context.insert<InstCast>(InstCast::Zext, ValExt, ValOp); |
| 766 | 761 |
| 767 // Technically, ARM has its own __aeabi_memset, but we can use plain | 762 // Technically, ARM has its own __aeabi_memset, but we can use plain |
| 768 // memset too. The value and size argument need to be flipped if we ever | 763 // memset too. The value and size argument need to be flipped if we ever |
| 769 // decide to use __aeabi_memset. | 764 // decide to use __aeabi_memset. |
| 770 static constexpr SizeT MaxArgs = 3; | 765 static constexpr SizeT MaxArgs = 3; |
| 771 static constexpr Variable *NoDest = nullptr; | 766 static constexpr Variable *NoDest = nullptr; |
| 772 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset); | 767 Operand *TargetHelper = getRuntimeHelperFunc(H_call_memset); |
| 773 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, | 768 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, |
| 774 NoTailCall, IsTargetHelperCall); | 769 NoTailCall, IsTargetHelperCall); |
| 775 Call->addArg(IntrinsicCall->getArg(0)); | 770 Call->addArg(IntrinsicCall->getArg(0)); |
| 776 Call->addArg(ValExt); | 771 Call->addArg(ValExt); |
| 777 Call->addArg(IntrinsicCall->getArg(2)); | 772 Call->addArg(IntrinsicCall->getArg(2)); |
| 778 Instr->setDeleted(); | 773 Instr->setDeleted(); |
| 779 return; | 774 return; |
| 780 } | 775 } |
| 781 case Intrinsics::NaClReadTP: { | 776 case Intrinsics::NaClReadTP: { |
| 782 if (SandboxingType == ST_NaCl) { | 777 if (SandboxingType == ST_NaCl) { |
| 783 return; | 778 return; |
| 784 } | 779 } |
| 785 static constexpr SizeT MaxArgs = 0; | 780 static constexpr SizeT MaxArgs = 0; |
| 786 const char *ReadTP = | 781 Operand *TargetHelper = SandboxingType == ST_Nonsfi |
| 787 SandboxingType == ST_Nonsfi ? "__aeabi_read_tp" : H_call_read_tp; | 782 ? Ctx->getConstantExternSym("__aeabi_read_tp") |
| 788 Operand *TargetHelper = Ctx->getConstantExternSym(ReadTP); | 783 : getRuntimeHelperFunc(H_call_read_tp); |
| 789 Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall, | 784 Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall, |
| 790 IsTargetHelperCall); | 785 IsTargetHelperCall); |
| 791 Instr->setDeleted(); | 786 Instr->setDeleted(); |
| 792 return; | 787 return; |
| 793 } | 788 } |
| 794 case Intrinsics::Setjmp: { | 789 case Intrinsics::Setjmp: { |
| 795 static constexpr SizeT MaxArgs = 1; | 790 static constexpr SizeT MaxArgs = 1; |
| 796 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_setjmp); | 791 Operand *TargetHelper = getRuntimeHelperFunc(H_call_setjmp); |
| 797 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 792 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
| 798 NoTailCall, IsTargetHelperCall); | 793 NoTailCall, IsTargetHelperCall); |
| 799 Call->addArg(IntrinsicCall->getArg(0)); | 794 Call->addArg(IntrinsicCall->getArg(0)); |
| 800 Instr->setDeleted(); | 795 Instr->setDeleted(); |
| 801 return; | 796 return; |
| 802 } | 797 } |
| 803 } | 798 } |
| 804 llvm::report_fatal_error("Control flow should never have reached here."); | 799 llvm::report_fatal_error("Control flow should never have reached here."); |
| 805 } | 800 } |
| 806 case Inst::Icmp: { | 801 case Inst::Icmp: { |
| (...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2712 if (ShAmtImm >= 32) { | 2707 if (ShAmtImm >= 32) { |
| 2713 if (ShAmtImm == 32) { | 2708 if (ShAmtImm == 32) { |
| 2714 _mov(DestHi, Src0RLo); | 2709 _mov(DestHi, Src0RLo); |
| 2715 } else { | 2710 } else { |
| 2716 Operand *ShAmtOp = shAmtImm(ShAmtImm - 32); | 2711 Operand *ShAmtOp = shAmtImm(ShAmtImm - 32); |
| 2717 _lsl(T_Hi, Src0RLo, ShAmtOp); | 2712 _lsl(T_Hi, Src0RLo, ShAmtOp); |
| 2718 _mov(DestHi, T_Hi); | 2713 _mov(DestHi, T_Hi); |
| 2719 } | 2714 } |
| 2720 | 2715 |
| 2721 Operand *_0 = | 2716 Operand *_0 = |
| 2722 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 2717 legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 2723 _mov(T_Lo, _0); | 2718 _mov(T_Lo, _0); |
| 2724 _mov(DestLo, T_Lo); | 2719 _mov(DestLo, T_Lo); |
| 2725 return; | 2720 return; |
| 2726 } | 2721 } |
| 2727 | 2722 |
| 2728 Variable *Src0RHi = SrcsHi.src0R(this); | 2723 Variable *Src0RHi = SrcsHi.src0R(this); |
| 2729 Operand *ShAmtOp = shAmtImm(ShAmtImm); | 2724 Operand *ShAmtOp = shAmtImm(ShAmtImm); |
| 2730 Operand *ComplShAmtOp = shAmtImm(32 - ShAmtImm); | 2725 Operand *ComplShAmtOp = shAmtImm(32 - ShAmtImm); |
| 2731 _lsl(T_Hi, Src0RHi, ShAmtOp); | 2726 _lsl(T_Hi, Src0RHi, ShAmtOp); |
| 2732 _orr(T_Hi, T_Hi, | 2727 _orr(T_Hi, T_Hi, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2765 // a.hi = t_hi | 2760 // a.hi = t_hi |
| 2766 // | 2761 // |
| 2767 // These are incompatible, therefore we mimic pnacl-llc. | 2762 // These are incompatible, therefore we mimic pnacl-llc. |
| 2768 // Can be strength-reduced for constant-shifts, but we don't do that for | 2763 // Can be strength-reduced for constant-shifts, but we don't do that for |
| 2769 // now. | 2764 // now. |
| 2770 // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. On | 2765 // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. On |
| 2771 // ARM, shifts only take the lower 8 bits of the shift register, and | 2766 // ARM, shifts only take the lower 8 bits of the shift register, and |
| 2772 // saturate to the range 0-32, so the negative value will saturate to 32. | 2767 // saturate to the range 0-32, so the negative value will saturate to 32. |
| 2773 Operand *_32 = legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); | 2768 Operand *_32 = legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); |
| 2774 Operand *_0 = | 2769 Operand *_0 = |
| 2775 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 2770 legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 2776 Variable *T0 = makeReg(IceType_i32); | 2771 Variable *T0 = makeReg(IceType_i32); |
| 2777 Variable *T1 = makeReg(IceType_i32); | 2772 Variable *T1 = makeReg(IceType_i32); |
| 2778 Variable *T2 = makeReg(IceType_i32); | 2773 Variable *T2 = makeReg(IceType_i32); |
| 2779 Variable *TA_Hi = makeReg(IceType_i32); | 2774 Variable *TA_Hi = makeReg(IceType_i32); |
| 2780 Variable *TA_Lo = makeReg(IceType_i32); | 2775 Variable *TA_Lo = makeReg(IceType_i32); |
| 2781 Variable *Src0RLo = SrcsLo.unswappedSrc0R(this); | 2776 Variable *Src0RLo = SrcsLo.unswappedSrc0R(this); |
| 2782 Variable *Src0RHi = SrcsHi.unswappedSrc0R(this); | 2777 Variable *Src0RHi = SrcsHi.unswappedSrc0R(this); |
| 2783 Variable *Src1RLo = SrcsLo.unswappedSrc1R(this); | 2778 Variable *Src1RLo = SrcsLo.unswappedSrc1R(this); |
| 2784 _rsb(T0, Src1RLo, _32); | 2779 _rsb(T0, Src1RLo, _32); |
| 2785 _lsr(T1, Src0RLo, T0); | 2780 _lsr(T1, Src0RLo, T0); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2817 } else { | 2812 } else { |
| 2818 _lsr(T_Lo, Src0RHi, ShAmtImm); | 2813 _lsr(T_Lo, Src0RHi, ShAmtImm); |
| 2819 } | 2814 } |
| 2820 _mov(DestLo, T_Lo); | 2815 _mov(DestLo, T_Lo); |
| 2821 } | 2816 } |
| 2822 | 2817 |
| 2823 if (ASR) { | 2818 if (ASR) { |
| 2824 Operand *_31 = shAmtImm(31); | 2819 Operand *_31 = shAmtImm(31); |
| 2825 _asr(T_Hi, Src0RHi, _31); | 2820 _asr(T_Hi, Src0RHi, _31); |
| 2826 } else { | 2821 } else { |
| 2827 Operand *_0 = legalize(Ctx->getConstantZero(IceType_i32), | 2822 Operand *_0 = |
| 2828 Legal_Reg | Legal_Flex); | 2823 legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 2829 _mov(T_Hi, _0); | 2824 _mov(T_Hi, _0); |
| 2830 } | 2825 } |
| 2831 _mov(DestHi, T_Hi); | 2826 _mov(DestHi, T_Hi); |
| 2832 return; | 2827 return; |
| 2833 } | 2828 } |
| 2834 | 2829 |
| 2835 Variable *Src0RLo = SrcsLo.src0R(this); | 2830 Variable *Src0RLo = SrcsLo.src0R(this); |
| 2836 Operand *ShAmtImm = shAmtImm(ShAmt); | 2831 Operand *ShAmtImm = shAmtImm(ShAmt); |
| 2837 Operand *ComplShAmtImm = shAmtImm(32 - ShAmt); | 2832 Operand *ComplShAmtImm = shAmtImm(32 - ShAmt); |
| 2838 _lsr(T_Lo, Src0RLo, ShAmtImm); | 2833 _lsr(T_Lo, Src0RLo, ShAmtImm); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2871 // orr t_lo, t_lo, b.hi, lsl t_c1 | 2866 // orr t_lo, t_lo, b.hi, lsl t_c1 |
| 2872 // sub t_c2, c.lo, #32 | 2867 // sub t_c2, c.lo, #32 |
| 2873 // orr t_lo, t_lo, b.hi, lsr t_c2 | 2868 // orr t_lo, t_lo, b.hi, lsr t_c2 |
| 2874 // lsr t_hi, b.hi, c.lo | 2869 // lsr t_hi, b.hi, c.lo |
| 2875 // mov a.lo, t_lo | 2870 // mov a.lo, t_lo |
| 2876 // mov a.hi, t_hi | 2871 // mov a.hi, t_hi |
| 2877 // | 2872 // |
| 2878 // These are incompatible, therefore we mimic pnacl-llc. | 2873 // These are incompatible, therefore we mimic pnacl-llc. |
| 2879 Operand *_32 = legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); | 2874 Operand *_32 = legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); |
| 2880 Operand *_0 = | 2875 Operand *_0 = |
| 2881 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 2876 legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 2882 Variable *T0 = makeReg(IceType_i32); | 2877 Variable *T0 = makeReg(IceType_i32); |
| 2883 Variable *T1 = makeReg(IceType_i32); | 2878 Variable *T1 = makeReg(IceType_i32); |
| 2884 Variable *T2 = makeReg(IceType_i32); | 2879 Variable *T2 = makeReg(IceType_i32); |
| 2885 Variable *TA_Lo = makeReg(IceType_i32); | 2880 Variable *TA_Lo = makeReg(IceType_i32); |
| 2886 Variable *TA_Hi = makeReg(IceType_i32); | 2881 Variable *TA_Hi = makeReg(IceType_i32); |
| 2887 Variable *Src0RLo = SrcsLo.unswappedSrc0R(this); | 2882 Variable *Src0RLo = SrcsLo.unswappedSrc0R(this); |
| 2888 Variable *Src0RHi = SrcsHi.unswappedSrc0R(this); | 2883 Variable *Src0RHi = SrcsHi.unswappedSrc0R(this); |
| 2889 Variable *Src1RLo = SrcsLo.unswappedSrc1R(this); | 2884 Variable *Src1RLo = SrcsLo.unswappedSrc1R(this); |
| 2890 _lsr(T0, Src0RLo, Src1RLo); | 2885 _lsr(T0, Src0RLo, Src1RLo); |
| 2891 _rsb(T1, Src1RLo, _32); | 2886 _rsb(T1, Src1RLo, _32); |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3337 } | 3332 } |
| 3338 case InstArithmetic::Mul: { | 3333 case InstArithmetic::Mul: { |
| 3339 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; | 3334 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; |
| 3340 if (!OptM1 && Srcs.hasConstOperand()) { | 3335 if (!OptM1 && Srcs.hasConstOperand()) { |
| 3341 constexpr std::size_t MaxShifts = 4; | 3336 constexpr std::size_t MaxShifts = 4; |
| 3342 std::array<StrengthReduction::AggregationElement, MaxShifts> Shifts; | 3337 std::array<StrengthReduction::AggregationElement, MaxShifts> Shifts; |
| 3343 SizeT NumOperations; | 3338 SizeT NumOperations; |
| 3344 int32_t Const = Srcs.getConstantValue(); | 3339 int32_t Const = Srcs.getConstantValue(); |
| 3345 const bool Invert = Const < 0; | 3340 const bool Invert = Const < 0; |
| 3346 const bool MultiplyByZero = Const == 0; | 3341 const bool MultiplyByZero = Const == 0; |
| 3347 Operand *_0 = | 3342 Operand *_0 = legalize(getConstantZero(DestTy), Legal_Reg | Legal_Flex); |
| 3348 legalize(Ctx->getConstantZero(DestTy), Legal_Reg | Legal_Flex); | |
| 3349 | 3343 |
| 3350 if (MultiplyByZero) { | 3344 if (MultiplyByZero) { |
| 3351 _mov(T, _0); | 3345 _mov(T, _0); |
| 3352 _mov(Dest, T); | 3346 _mov(Dest, T); |
| 3353 return; | 3347 return; |
| 3354 } | 3348 } |
| 3355 | 3349 |
| 3356 if (Invert) { | 3350 if (Invert) { |
| 3357 Const = -Const; | 3351 Const = -Const; |
| 3358 } | 3352 } |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3858 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 3852 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 3859 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 3853 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 3860 Variable *T_Lo = makeReg(DestLo->getType()); | 3854 Variable *T_Lo = makeReg(DestLo->getType()); |
| 3861 if (Src0->getType() == IceType_i32) { | 3855 if (Src0->getType() == IceType_i32) { |
| 3862 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); | 3856 Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
| 3863 _mov(T_Lo, Src0RF); | 3857 _mov(T_Lo, Src0RF); |
| 3864 } else if (Src0->getType() != IceType_i1) { | 3858 } else if (Src0->getType() != IceType_i1) { |
| 3865 Variable *Src0R = legalizeToReg(Src0); | 3859 Variable *Src0R = legalizeToReg(Src0); |
| 3866 _sxt(T_Lo, Src0R); | 3860 _sxt(T_Lo, Src0R); |
| 3867 } else { | 3861 } else { |
| 3868 Operand *_0 = Ctx->getConstantZero(IceType_i32); | 3862 Operand *_0 = getConstantZero(IceType_i32); |
| 3869 Operand *_m1 = Ctx->getConstantInt32(-1); | 3863 Operand *_m1 = Ctx->getConstantInt32(-1); |
| 3870 lowerInt1ForSelect(T_Lo, Src0, _m1, _0); | 3864 lowerInt1ForSelect(T_Lo, Src0, _m1, _0); |
| 3871 } | 3865 } |
| 3872 _mov(DestLo, T_Lo); | 3866 _mov(DestLo, T_Lo); |
| 3873 Variable *T_Hi = makeReg(DestHi->getType()); | 3867 Variable *T_Hi = makeReg(DestHi->getType()); |
| 3874 if (Src0->getType() != IceType_i1) { | 3868 if (Src0->getType() != IceType_i1) { |
| 3875 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo, | 3869 _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo, |
| 3876 OperandARM32::ASR, ShiftAmt)); | 3870 OperandARM32::ASR, ShiftAmt)); |
| 3877 } else { | 3871 } else { |
| 3878 // For i1, the asr instruction is already done above. | 3872 // For i1, the asr instruction is already done above. |
| 3879 _mov(T_Hi, T_Lo); | 3873 _mov(T_Hi, T_Lo); |
| 3880 } | 3874 } |
| 3881 _mov(DestHi, T_Hi); | 3875 _mov(DestHi, T_Hi); |
| 3882 } else if (Src0->getType() != IceType_i1) { | 3876 } else if (Src0->getType() != IceType_i1) { |
| 3883 // t1 = sxt src; dst = t1 | 3877 // t1 = sxt src; dst = t1 |
| 3884 Variable *Src0R = legalizeToReg(Src0); | 3878 Variable *Src0R = legalizeToReg(Src0); |
| 3885 Variable *T = makeReg(Dest->getType()); | 3879 Variable *T = makeReg(Dest->getType()); |
| 3886 _sxt(T, Src0R); | 3880 _sxt(T, Src0R); |
| 3887 _mov(Dest, T); | 3881 _mov(Dest, T); |
| 3888 } else { | 3882 } else { |
| 3889 Constant *_0 = Ctx->getConstantZero(IceType_i32); | 3883 Constant *_0 = getConstantZero(IceType_i32); |
| 3890 Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1); | 3884 Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1); |
| 3891 Variable *T = makeReg(Dest->getType()); | 3885 Variable *T = makeReg(Dest->getType()); |
| 3892 lowerInt1ForSelect(T, Src0, _m1, _0); | 3886 lowerInt1ForSelect(T, Src0, _m1, _0); |
| 3893 _mov(Dest, T); | 3887 _mov(Dest, T); |
| 3894 } | 3888 } |
| 3895 break; | 3889 break; |
| 3896 } | 3890 } |
| 3897 case InstCast::Zext: { | 3891 case InstCast::Zext: { |
| 3898 if (isVectorType(Dest->getType())) { | 3892 if (isVectorType(Dest->getType())) { |
| 3899 UnimplementedLoweringError(this, Instr); | 3893 UnimplementedLoweringError(this, Instr); |
| 3900 } else if (Dest->getType() == IceType_i64) { | 3894 } else if (Dest->getType() == IceType_i64) { |
| 3901 // t1=uxtb src; dst.lo=t1; dst.hi=0 | 3895 // t1=uxtb src; dst.lo=t1; dst.hi=0 |
| 3902 Operand *_0 = | 3896 Operand *_0 = |
| 3903 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 3897 legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 3904 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 3898 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 3905 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 3899 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 3906 Variable *T_Lo = makeReg(DestLo->getType()); | 3900 Variable *T_Lo = makeReg(DestLo->getType()); |
| 3907 | 3901 |
| 3908 switch (Src0->getType()) { | 3902 switch (Src0->getType()) { |
| 3909 default: { | 3903 default: { |
| 3910 assert(Src0->getType() != IceType_i64); | 3904 assert(Src0->getType() != IceType_i64); |
| 3911 _uxt(T_Lo, legalizeToReg(Src0)); | 3905 _uxt(T_Lo, legalizeToReg(Src0)); |
| 3912 } break; | 3906 } break; |
| 3913 case IceType_i32: { | 3907 case IceType_i32: { |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4246 | 4240 |
| 4247 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { | 4241 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { |
| 4248 Variable *Dest = Instr->getDest(); | 4242 Variable *Dest = Instr->getDest(); |
| 4249 if (isVectorType(Dest->getType())) { | 4243 if (isVectorType(Dest->getType())) { |
| 4250 UnimplementedLoweringError(this, Instr); | 4244 UnimplementedLoweringError(this, Instr); |
| 4251 return; | 4245 return; |
| 4252 } | 4246 } |
| 4253 | 4247 |
| 4254 Variable *T = makeReg(IceType_i1); | 4248 Variable *T = makeReg(IceType_i1); |
| 4255 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); | 4249 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
| 4256 Operand *_0 = | 4250 Operand *_0 = legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 4257 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | |
| 4258 | 4251 |
| 4259 CondWhenTrue Cond = lowerFcmpCond(Instr); | 4252 CondWhenTrue Cond = lowerFcmpCond(Instr); |
| 4260 | 4253 |
| 4261 bool RedefineT = false; | 4254 bool RedefineT = false; |
| 4262 if (Cond.WhenTrue0 != CondARM32::AL) { | 4255 if (Cond.WhenTrue0 != CondARM32::AL) { |
| 4263 _mov(T, _0); | 4256 _mov(T, _0); |
| 4264 RedefineT = true; | 4257 RedefineT = true; |
| 4265 } | 4258 } |
| 4266 | 4259 |
| 4267 if (Cond.WhenTrue0 == CondARM32::kNone) { | 4260 if (Cond.WhenTrue0 == CondARM32::kNone) { |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4544 } | 4537 } |
| 4545 | 4538 |
| 4546 void TargetARM32::lowerIcmp(const InstIcmp *Instr) { | 4539 void TargetARM32::lowerIcmp(const InstIcmp *Instr) { |
| 4547 Variable *Dest = Instr->getDest(); | 4540 Variable *Dest = Instr->getDest(); |
| 4548 | 4541 |
| 4549 if (isVectorType(Dest->getType())) { | 4542 if (isVectorType(Dest->getType())) { |
| 4550 UnimplementedLoweringError(this, Instr); | 4543 UnimplementedLoweringError(this, Instr); |
| 4551 return; | 4544 return; |
| 4552 } | 4545 } |
| 4553 | 4546 |
| 4554 Operand *_0 = | 4547 Operand *_0 = legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 4555 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | |
| 4556 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); | 4548 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
| 4557 Variable *T = makeReg(IceType_i1); | 4549 Variable *T = makeReg(IceType_i1); |
| 4558 | 4550 |
| 4559 _mov(T, _0); | 4551 _mov(T, _0); |
| 4560 CondWhenTrue Cond = lowerIcmpCond(Instr); | 4552 CondWhenTrue Cond = lowerIcmpCond(Instr); |
| 4561 _mov_redefined(T, _1, Cond.WhenTrue0); | 4553 _mov_redefined(T, _1, Cond.WhenTrue0); |
| 4562 _mov(Dest, T); | 4554 _mov(Dest, T); |
| 4563 | 4555 |
| 4564 assert(Cond.WhenTrue1 == CondARM32::kNone); | 4556 assert(Cond.WhenTrue1 == CondARM32::kNone); |
| 4565 | 4557 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4601 | 4593 |
| 4602 void TargetARM32::lowerLoadLinkedStoreExclusive( | 4594 void TargetARM32::lowerLoadLinkedStoreExclusive( |
| 4603 Type Ty, Operand *Addr, std::function<Variable *(Variable *)> Operation, | 4595 Type Ty, Operand *Addr, std::function<Variable *(Variable *)> Operation, |
| 4604 CondARM32::Cond Cond) { | 4596 CondARM32::Cond Cond) { |
| 4605 | 4597 |
| 4606 auto *Retry = Context.insert<InstARM32Label>(this); | 4598 auto *Retry = Context.insert<InstARM32Label>(this); |
| 4607 | 4599 |
| 4608 { // scoping for loop highlighting. | 4600 { // scoping for loop highlighting. |
| 4609 Variable *Success = makeReg(IceType_i32); | 4601 Variable *Success = makeReg(IceType_i32); |
| 4610 Variable *Tmp = (Ty == IceType_i64) ? makeI64RegPair() : makeReg(Ty); | 4602 Variable *Tmp = (Ty == IceType_i64) ? makeI64RegPair() : makeReg(Ty); |
| 4611 auto *_0 = Ctx->getConstantZero(IceType_i32); | 4603 auto *_0 = getConstantZero(IceType_i32); |
| 4612 | 4604 |
| 4613 Context.insert<InstFakeDef>(Tmp); | 4605 Context.insert<InstFakeDef>(Tmp); |
| 4614 Context.insert<InstFakeUse>(Tmp); | 4606 Context.insert<InstFakeUse>(Tmp); |
| 4615 Variable *AddrR = legalizeToReg(Addr); | 4607 Variable *AddrR = legalizeToReg(Addr); |
| 4616 _ldrex(Tmp, formMemoryOperand(AddrR, Ty))->setDestRedefined(); | 4608 _ldrex(Tmp, formMemoryOperand(AddrR, Ty))->setDestRedefined(); |
| 4617 auto *StoreValue = Operation(Tmp); | 4609 auto *StoreValue = Operation(Tmp); |
| 4618 assert(StoreValue->mustHaveReg()); | 4610 assert(StoreValue->mustHaveReg()); |
| 4619 // strex requires Dest to be a register other than Value or Addr. This | 4611 // strex requires Dest to be a register other than Value or Addr. This |
| 4620 // restriction is cleanly represented by adding an "early" definition of | 4612 // restriction is cleanly represented by adding an "early" definition of |
| 4621 // Dest (or a latter use of all the sources.) | 4613 // Dest (or a latter use of all the sources.) |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4766 Operand *Arg0 = Instr->getArg(0); | 4758 Operand *Arg0 = Instr->getArg(0); |
| 4767 if (isInt32Asserting32Or64(Arg0->getType())) { | 4759 if (isInt32Asserting32Or64(Arg0->getType())) { |
| 4768 return; | 4760 return; |
| 4769 } | 4761 } |
| 4770 // The popcount helpers always return 32-bit values, while the intrinsic's | 4762 // The popcount helpers always return 32-bit values, while the intrinsic's |
| 4771 // signature matches some 64-bit platform's native instructions and expect to | 4763 // signature matches some 64-bit platform's native instructions and expect to |
| 4772 // fill a 64-bit reg. Thus, clear the upper bits of the dest just in case the | 4764 // fill a 64-bit reg. Thus, clear the upper bits of the dest just in case the |
| 4773 // user doesn't do that in the IR or doesn't toss the bits via truncate. | 4765 // user doesn't do that in the IR or doesn't toss the bits via truncate. |
| 4774 auto *DestHi = llvm::cast<Variable>(hiOperand(Instr->getDest())); | 4766 auto *DestHi = llvm::cast<Variable>(hiOperand(Instr->getDest())); |
| 4775 Variable *T = makeReg(IceType_i32); | 4767 Variable *T = makeReg(IceType_i32); |
| 4776 Operand *_0 = | 4768 Operand *_0 = legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 4777 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | |
| 4778 _mov(T, _0); | 4769 _mov(T, _0); |
| 4779 _mov(DestHi, T); | 4770 _mov(DestHi, T); |
| 4780 } | 4771 } |
| 4781 | 4772 |
| 4782 void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { | 4773 void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
| 4783 Variable *Dest = Instr->getDest(); | 4774 Variable *Dest = Instr->getDest(); |
| 4784 Type DestTy = (Dest != nullptr) ? Dest->getType() : IceType_void; | 4775 Type DestTy = (Dest != nullptr) ? Dest->getType() : IceType_void; |
| 4785 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID; | 4776 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID; |
| 4786 switch (ID) { | 4777 switch (ID) { |
| 4787 case Intrinsics::AtomicFence: | 4778 case Intrinsics::AtomicFence: |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5057 } | 5048 } |
| 5058 case Intrinsics::Memset: { | 5049 case Intrinsics::Memset: { |
| 5059 llvm::report_fatal_error("memmove should have been prelowered."); | 5050 llvm::report_fatal_error("memmove should have been prelowered."); |
| 5060 } | 5051 } |
| 5061 case Intrinsics::NaClReadTP: { | 5052 case Intrinsics::NaClReadTP: { |
| 5062 if (SandboxingType != ST_NaCl) { | 5053 if (SandboxingType != ST_NaCl) { |
| 5063 llvm::report_fatal_error("nacl-read-tp should have been prelowered."); | 5054 llvm::report_fatal_error("nacl-read-tp should have been prelowered."); |
| 5064 } | 5055 } |
| 5065 Variable *TP = legalizeToReg(OperandARM32Mem::create( | 5056 Variable *TP = legalizeToReg(OperandARM32Mem::create( |
| 5066 Func, getPointerType(), getPhysicalRegister(RegARM32::Reg_r9), | 5057 Func, getPointerType(), getPhysicalRegister(RegARM32::Reg_r9), |
| 5067 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)))); | 5058 llvm::cast<ConstantInteger32>(getConstantZero(IceType_i32)))); |
| 5068 _mov(Dest, TP); | 5059 _mov(Dest, TP); |
| 5069 return; | 5060 return; |
| 5070 } | 5061 } |
| 5071 case Intrinsics::Setjmp: { | 5062 case Intrinsics::Setjmp: { |
| 5072 llvm::report_fatal_error("setjmp should have been prelowered."); | 5063 llvm::report_fatal_error("setjmp should have been prelowered."); |
| 5073 } | 5064 } |
| 5074 case Intrinsics::Sqrt: { | 5065 case Intrinsics::Sqrt: { |
| 5075 Variable *Src = legalizeToReg(Instr->getArg(0)); | 5066 Variable *Src = legalizeToReg(Instr->getArg(0)); |
| 5076 Variable *T = makeReg(Dest->getType()); | 5067 Variable *T = makeReg(Dest->getType()); |
| 5077 _vsqrt(T, Src); | 5068 _vsqrt(T, Src); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 5100 | 5091 |
| 5101 void TargetARM32::lowerCLZ(Variable *Dest, Variable *ValLoR, Variable *ValHiR) { | 5092 void TargetARM32::lowerCLZ(Variable *Dest, Variable *ValLoR, Variable *ValHiR) { |
| 5102 Type Ty = Dest->getType(); | 5093 Type Ty = Dest->getType(); |
| 5103 assert(Ty == IceType_i32 || Ty == IceType_i64); | 5094 assert(Ty == IceType_i32 || Ty == IceType_i64); |
| 5104 Variable *T = makeReg(IceType_i32); | 5095 Variable *T = makeReg(IceType_i32); |
| 5105 _clz(T, ValLoR); | 5096 _clz(T, ValLoR); |
| 5106 if (Ty == IceType_i64) { | 5097 if (Ty == IceType_i64) { |
| 5107 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 5098 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 5108 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 5099 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 5109 Operand *Zero = | 5100 Operand *Zero = |
| 5110 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 5101 legalize(getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
| 5111 Operand *ThirtyTwo = | 5102 Operand *ThirtyTwo = |
| 5112 legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); | 5103 legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex); |
| 5113 _cmp(ValHiR, Zero); | 5104 _cmp(ValHiR, Zero); |
| 5114 Variable *T2 = makeReg(IceType_i32); | 5105 Variable *T2 = makeReg(IceType_i32); |
| 5115 _add(T2, T, ThirtyTwo); | 5106 _add(T2, T, ThirtyTwo); |
| 5116 _clz(T2, ValHiR, CondARM32::NE); | 5107 _clz(T2, ValHiR, CondARM32::NE); |
| 5117 // T2 is actually a source as well when the predicate is not AL (since it | 5108 // T2 is actually a source as well when the predicate is not AL (since it |
| 5118 // may leave T2 alone). We use _set_dest_redefined to prolong the liveness | 5109 // may leave T2 alone). We use _set_dest_redefined to prolong the liveness |
| 5119 // of T2 as if it was used as a source. | 5110 // of T2 as if it was used as a source. |
| 5120 _set_dest_redefined(); | 5111 _set_dest_redefined(); |
| (...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6044 // in less predictable code. | 6035 // in less predictable code. |
| 6045 // | 6036 // |
| 6046 // If in the future the implementation is changed to lower undef values to | 6037 // If in the future the implementation is changed to lower undef values to |
| 6047 // uninitialized registers, a FakeDef will be needed: | 6038 // uninitialized registers, a FakeDef will be needed: |
| 6048 // Context.insert(InstFakeDef::create(Func, Reg)); This is in order to | 6039 // Context.insert(InstFakeDef::create(Func, Reg)); This is in order to |
| 6049 // ensure that the live range of Reg is not overestimated. If the constant | 6040 // ensure that the live range of Reg is not overestimated. If the constant |
| 6050 // being lowered is a 64 bit value, then the result should be split and the | 6041 // being lowered is a 64 bit value, then the result should be split and the |
| 6051 // lo and hi components will need to go in uninitialized registers. | 6042 // lo and hi components will need to go in uninitialized registers. |
| 6052 if (isVectorType(Ty)) | 6043 if (isVectorType(Ty)) |
| 6053 return makeVectorOfZeros(Ty, RegNum); | 6044 return makeVectorOfZeros(Ty, RegNum); |
| 6054 return Ctx->getConstantZero(Ty); | 6045 return getConstantZero(Ty); |
| 6055 } | 6046 } |
| 6056 return From; | 6047 return From; |
| 6057 } | 6048 } |
| 6058 | 6049 |
| 6059 OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) { | 6050 OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) { |
| 6060 auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); | 6051 auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand); |
| 6061 // It may be the case that address mode optimization already creates an | 6052 // It may be the case that address mode optimization already creates an |
| 6062 // OperandARM32Mem, so in that case it wouldn't need another level of | 6053 // OperandARM32Mem, so in that case it wouldn't need another level of |
| 6063 // transformation. | 6054 // transformation. |
| 6064 if (Mem) { | 6055 if (Mem) { |
| 6065 return llvm::cast<OperandARM32Mem>(legalize(Mem)); | 6056 return llvm::cast<OperandARM32Mem>(legalize(Mem)); |
| 6066 } | 6057 } |
| 6067 // If we didn't do address mode optimization, then we only have a | 6058 // If we didn't do address mode optimization, then we only have a |
| 6068 // base/offset to work with. ARM always requires a base register, so | 6059 // base/offset to work with. ARM always requires a base register, so |
| 6069 // just use that to hold the operand. | 6060 // just use that to hold the operand. |
| 6070 auto *Base = llvm::cast<Variable>( | 6061 auto *Base = llvm::cast<Variable>( |
| 6071 legalize(Operand, Legal_Reg | Legal_Rematerializable)); | 6062 legalize(Operand, Legal_Reg | Legal_Rematerializable)); |
| 6072 return OperandARM32Mem::create( | 6063 return OperandARM32Mem::create( |
| 6073 Func, Ty, Base, | 6064 Func, Ty, Base, |
| 6074 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))); | 6065 llvm::cast<ConstantInteger32>(getConstantZero(IceType_i32))); |
| 6075 } | 6066 } |
| 6076 | 6067 |
| 6077 Variable64On32 *TargetARM32::makeI64RegPair() { | 6068 Variable64On32 *TargetARM32::makeI64RegPair() { |
| 6078 Variable64On32 *Reg = | 6069 Variable64On32 *Reg = |
| 6079 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); | 6070 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 6080 Reg->setMustHaveReg(); | 6071 Reg->setMustHaveReg(); |
| 6081 Reg->initHiLo(Func); | 6072 Reg->initHiLo(Func); |
| 6082 Reg->getLo()->setMustNotHaveReg(); | 6073 Reg->getLo()->setMustNotHaveReg(); |
| 6083 Reg->getHi()->setMustNotHaveReg(); | 6074 Reg->getHi()->setMustNotHaveReg(); |
| 6084 return Reg; | 6075 return Reg; |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6287 _mov(DestLo, T_Lo); | 6278 _mov(DestLo, T_Lo); |
| 6288 if (DestHi) { | 6279 if (DestHi) { |
| 6289 _mov(DestHi, T_Hi); | 6280 _mov(DestHi, T_Hi); |
| 6290 } | 6281 } |
| 6291 } | 6282 } |
| 6292 | 6283 |
| 6293 TargetARM32::SafeBoolChain TargetARM32::lowerInt1(Variable *Dest, | 6284 TargetARM32::SafeBoolChain TargetARM32::lowerInt1(Variable *Dest, |
| 6294 Operand *Boolean) { | 6285 Operand *Boolean) { |
| 6295 assert(Boolean->getType() == IceType_i1); | 6286 assert(Boolean->getType() == IceType_i1); |
| 6296 Variable *T = makeReg(IceType_i1); | 6287 Variable *T = makeReg(IceType_i1); |
| 6297 Operand *_0 = | 6288 Operand *_0 = legalize(getConstantZero(IceType_i1), Legal_Reg | Legal_Flex); |
| 6298 legalize(Ctx->getConstantZero(IceType_i1), Legal_Reg | Legal_Flex); | |
| 6299 Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex); | 6289 Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex); |
| 6300 | 6290 |
| 6301 SafeBoolChain Safe = SBC_Yes; | 6291 SafeBoolChain Safe = SBC_Yes; |
| 6302 if (const Inst *Producer = Computations.getProducerOf(Boolean)) { | 6292 if (const Inst *Producer = Computations.getProducerOf(Boolean)) { |
| 6303 switch (Producer->getKind()) { | 6293 switch (Producer->getKind()) { |
| 6304 default: | 6294 default: |
| 6305 llvm::report_fatal_error("Unexpected producer."); | 6295 llvm::report_fatal_error("Unexpected producer."); |
| 6306 case Inst::Icmp: { | 6296 case Inst::Icmp: { |
| 6307 _mov(T, _0); | 6297 _mov(T, _0); |
| 6308 CondWhenTrue Cond = lowerIcmpCond(llvm::cast<InstIcmp>(Producer)); | 6298 CondWhenTrue Cond = lowerIcmpCond(llvm::cast<InstIcmp>(Producer)); |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6893 // However, for compatibility with current NaCl LLVM, don't claim that. | 6883 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 6894 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6884 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6895 } | 6885 } |
| 6896 | 6886 |
| 6897 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; | 6887 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; |
| 6898 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; | 6888 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; |
| 6899 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6889 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6900 | 6890 |
| 6901 } // end of namespace ARM32 | 6891 } // end of namespace ARM32 |
| 6902 } // end of namespace Ice | 6892 } // end of namespace Ice |
| OLD | NEW |