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 |