Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===// | 1 //===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 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 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 564 UsesFramePointer = true; | 564 UsesFramePointer = true; |
| 565 // Conservatively require the stack to be aligned. Some stack adjustment | 565 // Conservatively require the stack to be aligned. Some stack adjustment |
| 566 // operations implemented below assume that the stack is aligned before the | 566 // operations implemented below assume that the stack is aligned before the |
| 567 // alloca. All the alloca code ensures that the stack alignment is preserved | 567 // alloca. All the alloca code ensures that the stack alignment is preserved |
| 568 // after the alloca. The stack alignment restriction can be relaxed in some | 568 // after the alloca. The stack alignment restriction can be relaxed in some |
| 569 // cases. | 569 // cases. |
| 570 NeedsStackAlignment = true; | 570 NeedsStackAlignment = true; |
| 571 UnimplementedLoweringError(this, Inst); | 571 UnimplementedLoweringError(this, Inst); |
| 572 } | 572 } |
| 573 | 573 |
| 574 void TargetMIPS32::lowerInt64Arithmetic(const InstArithmetic *Inst, | |
| 575 Variable *Dest, Operand *Src0, | |
| 576 Operand *Src1) { | |
| 577 InstArithmetic::OpKind Op = Inst->getOp(); | |
| 578 switch (Op) { | |
| 579 case InstArithmetic::Add: | |
| 580 case InstArithmetic::And: | |
| 581 case InstArithmetic::Or: | |
| 582 case InstArithmetic::Sub: | |
| 583 case InstArithmetic::Xor: | |
| 584 break; | |
| 585 default: | |
| 586 UnimplementedLoweringError(this, Inst); | |
| 587 return; | |
| 588 } | |
| 589 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | |
| 590 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | |
| 591 Variable *Src0LoR = legalizeToReg(loOperand(Src0), Legal_Reg); | |
|
Jim Stichnoth
2016/01/31 05:29:47
Remove the Legal_Reg optional argument.
That argu
rkotlerimgtec
2016/01/31 21:06:12
Done.
| |
| 592 Variable *Src1LoR = legalizeToReg(loOperand(Src1), Legal_Reg); | |
| 593 Variable *Src0HiR = legalizeToReg(hiOperand(Src0), Legal_Reg); | |
| 594 Variable *Src1HiR = legalizeToReg(hiOperand(Src1), Legal_Reg); | |
| 595 | |
| 596 switch (Op) { | |
| 597 case InstArithmetic::_num: | |
| 598 llvm::report_fatal_error("Unknown arithmetic operator"); | |
| 599 return; | |
| 600 case InstArithmetic::Add: { | |
| 601 Variable *T_Carry = makeReg(IceType_i32); | |
| 602 Variable *T_Lo = makeReg(IceType_i32); | |
| 603 Variable *T_Hi = makeReg(IceType_i32); | |
| 604 Variable *T_Hi2 = makeReg(IceType_i32); | |
|
Jim Stichnoth
2016/01/31 05:29:47
You can remove this T_Hi2 and reuse T_Hi instead.
rkotlerimgtec
2016/01/31 21:06:12
I would rather address this issue in another patch
| |
| 605 _addu(T_Lo, Src0LoR, Src1LoR); | |
| 606 _mov(DestLo, T_Lo); | |
| 607 _sltu(T_Carry, DestLo, Src0LoR); | |
|
Jim Stichnoth
2016/01/31 05:29:47
Use T_Lo instead of DestLo here, since DestLo isn'
rkotlerimgtec
2016/01/31 21:06:12
Done.
| |
| 608 _addu(T_Hi, T_Carry, Src0HiR); | |
| 609 _addu(T_Hi2, Src1HiR, T_Hi); | |
| 610 _mov(DestHi, T_Hi2); | |
| 611 return; | |
| 612 } | |
| 613 case InstArithmetic::And: { | |
| 614 Variable *T_Lo = makeReg(IceType_i32); | |
| 615 Variable *T_Hi = makeReg(IceType_i32); | |
| 616 _and(T_Lo, Src0LoR, Src1LoR); | |
| 617 _mov(DestLo, T_Lo); | |
| 618 _and(T_Hi, Src0HiR, Src1HiR); | |
| 619 _mov(DestHi, T_Hi); | |
| 620 return; | |
| 621 } | |
| 622 case InstArithmetic::Sub: { | |
| 623 Variable *T_Borrow = makeReg(IceType_i32); | |
| 624 Variable *T_Lo = makeReg(IceType_i32); | |
| 625 Variable *T_Hi = makeReg(IceType_i32); | |
| 626 Variable *T_Hi2 = makeReg(IceType_i32); | |
| 627 _subu(T_Lo, Src0LoR, Src1LoR); | |
| 628 _mov(DestLo, T_Lo); | |
| 629 _sltu(T_Borrow, Src0LoR, Src1LoR); | |
| 630 _addu(T_Hi, T_Borrow, Src1HiR); | |
| 631 _subu(T_Hi2, Src0HiR, T_Hi); | |
| 632 _mov(DestHi, T_Hi2); | |
| 633 return; | |
| 634 } | |
| 635 case InstArithmetic::Or: { | |
| 636 Variable *T_Lo = makeReg(IceType_i32); | |
| 637 Variable *T_Hi = makeReg(IceType_i32); | |
| 638 _or(T_Lo, Src0LoR, Src1LoR); | |
| 639 _mov(DestLo, T_Lo); | |
| 640 _or(T_Hi, Src0HiR, Src1HiR); | |
| 641 _mov(DestHi, T_Hi); | |
| 642 return; | |
| 643 } | |
| 644 case InstArithmetic::Xor: { | |
| 645 Variable *T_Lo = makeReg(IceType_i32); | |
| 646 Variable *T_Hi = makeReg(IceType_i32); | |
| 647 _xor(T_Lo, Src0LoR, Src1LoR); | |
| 648 _mov(DestLo, T_Lo); | |
| 649 _xor(T_Hi, Src0HiR, Src1HiR); | |
| 650 _mov(DestHi, T_Hi); | |
| 651 return; | |
| 652 } | |
| 653 default: | |
| 654 UnimplementedLoweringError(this, Inst); | |
| 655 return; | |
| 656 } | |
| 657 } | |
| 658 | |
| 574 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { | 659 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { |
| 575 Variable *Dest = Inst->getDest(); | 660 Variable *Dest = Inst->getDest(); |
| 576 // We need to signal all the UnimplementedLoweringError errors before any | 661 // We need to signal all the UnimplementedLoweringError errors before any |
| 577 // legalization into new variables, otherwise Om1 register allocation may fail | 662 // legalization into new variables, otherwise Om1 register allocation may fail |
| 578 // when it sees variables that are defined but not used. | 663 // when it sees variables that are defined but not used. |
| 579 if (Dest->getType() == IceType_i64) { | 664 Type DestTy = Dest->getType(); |
| 580 UnimplementedLoweringError(this, Inst); | 665 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
| 666 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | |
| 667 if (DestTy == IceType_i64) { | |
| 668 lowerInt64Arithmetic(Inst, Inst->getDest(), Src0, Src1); | |
| 581 return; | 669 return; |
| 582 } | 670 } |
| 583 if (isVectorType(Dest->getType())) { | 671 if (isVectorType(Dest->getType())) { |
| 584 UnimplementedLoweringError(this, Inst); | 672 UnimplementedLoweringError(this, Inst); |
| 585 return; | 673 return; |
| 586 } | 674 } |
| 587 switch (Inst->getOp()) { | 675 switch (Inst->getOp()) { |
| 588 default: | 676 default: |
| 589 break; | 677 break; |
| 590 case InstArithmetic::Shl: | 678 case InstArithmetic::Shl: |
| 591 case InstArithmetic::Lshr: | 679 case InstArithmetic::Lshr: |
| 592 case InstArithmetic::Ashr: | 680 case InstArithmetic::Ashr: |
| 593 case InstArithmetic::Udiv: | 681 case InstArithmetic::Udiv: |
| 594 case InstArithmetic::Sdiv: | 682 case InstArithmetic::Sdiv: |
| 595 case InstArithmetic::Urem: | 683 case InstArithmetic::Urem: |
| 596 case InstArithmetic::Srem: | 684 case InstArithmetic::Srem: |
| 597 case InstArithmetic::Fadd: | 685 case InstArithmetic::Fadd: |
| 598 case InstArithmetic::Fsub: | 686 case InstArithmetic::Fsub: |
| 599 case InstArithmetic::Fmul: | 687 case InstArithmetic::Fmul: |
| 600 case InstArithmetic::Fdiv: | 688 case InstArithmetic::Fdiv: |
| 601 case InstArithmetic::Frem: | 689 case InstArithmetic::Frem: |
| 602 UnimplementedLoweringError(this, Inst); | 690 UnimplementedLoweringError(this, Inst); |
| 603 return; | 691 return; |
| 604 } | 692 } |
| 605 | 693 |
| 606 // At this point Dest->getType() is non-i64 scalar | 694 // At this point Dest->getType() is non-i64 scalar |
| 607 | 695 |
| 608 Variable *T = makeReg(Dest->getType()); | 696 Variable *T = makeReg(Dest->getType()); |
| 609 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | |
| 610 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | |
| 611 Variable *Src0R = legalizeToReg(Src0); | 697 Variable *Src0R = legalizeToReg(Src0); |
| 612 Variable *Src1R = legalizeToReg(Src1); | 698 Variable *Src1R = legalizeToReg(Src1); |
| 613 | 699 |
| 614 switch (Inst->getOp()) { | 700 switch (Inst->getOp()) { |
| 615 case InstArithmetic::_num: | 701 case InstArithmetic::_num: |
| 616 break; | 702 break; |
| 617 case InstArithmetic::Add: | 703 case InstArithmetic::Add: |
| 618 _add(T, Src0R, Src1R); | 704 _add(T, Src0R, Src1R); |
| 619 _mov(Dest, T); | 705 _mov(Dest, T); |
| 620 return; | 706 return; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 657 break; | 743 break; |
| 658 case InstArithmetic::Fsub: | 744 case InstArithmetic::Fsub: |
| 659 break; | 745 break; |
| 660 case InstArithmetic::Fmul: | 746 case InstArithmetic::Fmul: |
| 661 break; | 747 break; |
| 662 case InstArithmetic::Fdiv: | 748 case InstArithmetic::Fdiv: |
| 663 break; | 749 break; |
| 664 case InstArithmetic::Frem: | 750 case InstArithmetic::Frem: |
| 665 break; | 751 break; |
| 666 } | 752 } |
| 753 UnimplementedLoweringError(this, Inst); | |
| 667 } | 754 } |
| 668 | 755 |
| 669 void TargetMIPS32::lowerAssign(const InstAssign *Inst) { | 756 void TargetMIPS32::lowerAssign(const InstAssign *Inst) { |
| 670 Variable *Dest = Inst->getDest(); | 757 Variable *Dest = Inst->getDest(); |
| 671 Operand *Src0 = Inst->getSrc(0); | 758 Operand *Src0 = Inst->getSrc(0); |
| 672 assert(Dest->getType() == Src0->getType()); | 759 assert(Dest->getType() == Src0->getType()); |
| 673 if (Dest->getType() == IceType_i64) { | 760 if (Dest->getType() == IceType_i64) { |
| 674 Src0 = legalizeUndef(Src0); | 761 Src0 = legalizeUndef(Src0); |
| 675 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); | 762 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); |
| 676 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); | 763 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 701 } else { | 788 } else { |
| 702 _mov(Dest, SrcR); | 789 _mov(Dest, SrcR); |
| 703 } | 790 } |
| 704 } | 791 } |
| 705 } | 792 } |
| 706 | 793 |
| 707 void TargetMIPS32::lowerBr(const InstBr *Inst) { | 794 void TargetMIPS32::lowerBr(const InstBr *Inst) { |
| 708 UnimplementedLoweringError(this, Inst); | 795 UnimplementedLoweringError(this, Inst); |
| 709 } | 796 } |
| 710 | 797 |
| 711 void TargetMIPS32::lowerCall(const InstCall *Inst) { | 798 void TargetMIPS32::lowerCall(const InstCall *Instr) { |
| 712 UnimplementedLoweringError(this, Inst); | 799 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. |
| 800 if (Instr->getNumArgs()) { | |
| 801 UnimplementedLoweringError(this, Instr); | |
| 802 return; | |
| 803 } | |
| 804 // Generate the call instruction. Assign its result to a temporary with high | |
| 805 // register allocation weight. | |
| 806 Variable *Dest = Instr->getDest(); | |
| 807 // ReturnReg doubles as ReturnRegLo as necessary. | |
| 808 Variable *ReturnReg = nullptr; | |
| 809 Variable *ReturnRegHi = nullptr; | |
| 810 if (Dest) { | |
| 811 switch (Dest->getType()) { | |
| 812 case IceType_NUM: | |
| 813 llvm_unreachable("Invalid Call dest type"); | |
| 814 return; | |
| 815 case IceType_void: | |
| 816 break; | |
| 817 case IceType_i1: | |
| 818 case IceType_i8: | |
| 819 case IceType_i16: | |
| 820 case IceType_i32: | |
| 821 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_V0); | |
| 822 break; | |
| 823 case IceType_i64: | |
| 824 ReturnReg = makeReg(IceType_i32, RegMIPS32::Reg_V0); | |
| 825 ReturnRegHi = makeReg(IceType_i32, RegMIPS32::Reg_V1); | |
| 826 break; | |
| 827 case IceType_f32: | |
| 828 case IceType_f64: | |
| 829 UnimplementedLoweringError(this, Instr); | |
| 830 return; | |
| 831 case IceType_v4i1: | |
| 832 case IceType_v8i1: | |
| 833 case IceType_v16i1: | |
| 834 case IceType_v16i8: | |
| 835 case IceType_v8i16: | |
| 836 case IceType_v4i32: | |
| 837 case IceType_v4f32: | |
| 838 UnimplementedLoweringError(this, Instr); | |
| 839 return; | |
| 840 } | |
| 841 } | |
| 842 Operand *CallTarget = Instr->getCallTarget(); | |
| 843 // Allow ConstantRelocatable to be left alone as a direct call, | |
| 844 // but force other constants like ConstantInteger32 to be in | |
| 845 // a register and make it an indirect call. | |
| 846 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | |
| 847 CallTarget = legalize(CallTarget, Legal_Reg); | |
| 848 } | |
| 849 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); | |
| 850 Context.insert(NewCall); | |
| 851 if (ReturnRegHi) | |
| 852 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | |
| 853 // Insert a register-kill pseudo instruction. | |
| 854 Context.insert(InstFakeKill::create(Func, NewCall)); | |
| 855 // Generate a FakeUse to keep the call live if necessary. | |
| 856 if (Instr->hasSideEffects() && ReturnReg) { | |
| 857 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | |
| 858 Context.insert(FakeUse); | |
| 859 } | |
| 860 if (Dest == nullptr) | |
| 861 return; | |
| 862 | |
| 863 // Assign the result of the call to Dest. | |
| 864 if (ReturnReg) { | |
| 865 if (ReturnRegHi) { | |
| 866 assert(Dest->getType() == IceType_i64); | |
| 867 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | |
| 868 Variable *DestLo = Dest64On32->getLo(); | |
| 869 Variable *DestHi = Dest64On32->getHi(); | |
| 870 _mov(DestLo, ReturnReg); | |
| 871 _mov(DestHi, ReturnRegHi); | |
| 872 } else { | |
| 873 assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || | |
| 874 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || | |
| 875 isVectorType(Dest->getType())); | |
| 876 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | |
| 877 UnimplementedLoweringError(this, Instr); | |
| 878 return; | |
| 879 } else { | |
| 880 _mov(Dest, ReturnReg); | |
| 881 } | |
| 882 } | |
| 883 } | |
| 884 UnimplementedLoweringError(this, Instr); | |
| 713 } | 885 } |
| 714 | 886 |
| 715 void TargetMIPS32::lowerCast(const InstCast *Inst) { | 887 void TargetMIPS32::lowerCast(const InstCast *Inst) { |
| 716 InstCast::OpKind CastKind = Inst->getCastKind(); | 888 InstCast::OpKind CastKind = Inst->getCastKind(); |
| 717 switch (CastKind) { | 889 switch (CastKind) { |
| 718 default: | 890 default: |
| 719 Func->setError("Cast type not supported"); | 891 Func->setError("Cast type not supported"); |
| 720 return; | 892 return; |
| 721 case InstCast::Sext: { | 893 case InstCast::Sext: { |
| 722 UnimplementedLoweringError(this, Inst); | 894 UnimplementedLoweringError(this, Inst); |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1080 // if a Flexible second operand is allowed. We need to know the exact | 1252 // if a Flexible second operand is allowed. We need to know the exact |
| 1081 // value, so that rules out relocatable constants. | 1253 // value, so that rules out relocatable constants. |
| 1082 // Also try the inverse and use MVN if possible. | 1254 // Also try the inverse and use MVN if possible. |
| 1083 // Do a movw/movt to a register. | 1255 // Do a movw/movt to a register. |
| 1084 Variable *Reg; | 1256 Variable *Reg; |
| 1085 if (RegNum == Variable::NoRegister) | 1257 if (RegNum == Variable::NoRegister) |
| 1086 Reg = makeReg(Ty, RegNum); | 1258 Reg = makeReg(Ty, RegNum); |
| 1087 else | 1259 else |
| 1088 Reg = getPhysicalRegister(RegNum); | 1260 Reg = getPhysicalRegister(RegNum); |
| 1089 if (isInt<16>(int32_t(Value))) { | 1261 if (isInt<16>(int32_t(Value))) { |
| 1090 _addiu(Reg, getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty), Value); | 1262 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); |
| 1263 Context.insert<InstFakeDef>(Zero); | |
| 1264 _addiu(Reg, Zero, Value); | |
| 1091 } else { | 1265 } else { |
| 1092 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | 1266 uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
| 1093 (void)UpperBits; | 1267 (void)UpperBits; |
| 1094 uint32_t LowerBits = Value & 0xFFFF; | 1268 uint32_t LowerBits = Value & 0xFFFF; |
| 1095 Variable *TReg = makeReg(Ty, RegNum); | 1269 Variable *TReg = makeReg(Ty, RegNum); |
| 1096 _lui(TReg, UpperBits); | 1270 _lui(TReg, UpperBits); |
| 1097 _ori(Reg, TReg, LowerBits); | 1271 _ori(Reg, TReg, LowerBits); |
| 1098 } | 1272 } |
| 1099 return Reg; | 1273 return Reg; |
| 1100 } | 1274 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1127 Str << "\t.set\t" | 1301 Str << "\t.set\t" |
| 1128 << "nomips16\n"; | 1302 << "nomips16\n"; |
| 1129 } | 1303 } |
| 1130 | 1304 |
| 1131 llvm::SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1305 llvm::SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
| 1132 llvm::SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1306 llvm::SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
| 1133 llvm::SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1307 llvm::SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
| 1134 | 1308 |
| 1135 } // end of namespace MIPS32 | 1309 } // end of namespace MIPS32 |
| 1136 } // end of namespace Ice | 1310 } // end of namespace Ice |
| OLD | NEW |